每日力扣-三等分

84 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天,点击查看活动详情

每日力扣是一个专门用来讲力扣中国每天发布的每日一题的栏目。本专栏不提供题目的解答源码,只讲解思路,目的是养成每日刷题、提高自己手感,从而达到算法熟练的目标。

题目(已做删减处理)

给定一个由 0 和 1 组成的数组 arr ,将数组分成  3 个非空的部分 ,使得所有这些部分表示相同的二进制值。如果可以做到,请返回任何 [i, j],其中 i+1 < j,这样一来:arr[0], arr[1], ..., arr[i] 为第一部分;arr[i + 1], arr[i + 2], ..., arr[j - 1] 为第二部分arr[j], arr[j + 1], ..., arr[arr.length - 1] 为第三部分。这三个部分所表示的二进制值相等。

分析

一道经典的模拟题。力扣上评价为hard,的确有其困难性。主要是其需要考虑的情况特别多。如果有人在力扣上一直刷题,或者是有人一直在力扣上打比赛,估计就有印象了。这道题目是力扣 107 场周赛的第 3 道题目。众所周知,力扣前 2 道题目,属于算法新人题,第3道题目就加强了难度。这道题目,也是如此。其中涉及到的逻辑处理和判断,需要同学们好好考虑。 根据题目的要求和逻辑,我们可以得到以下的思路:

  1. 如果数组中全都是0,则返回0,n-1即可;
if(arr[0].length()==0){return new int[]{0,arr.length()-1};
  1. 数组里面的1当是3的倍数是才能满足条件,其他的情况下,返回-1,-1即可;
if(arr[0]%3!=0) return new int[]{-1,-1};
  1. 当为3的倍数时,按照“三等分”的要求,找出每个部分的1即可,然后依次遍历,满足条件的返回对应的坐标即可。
//代码量太多,有凑字数的嫌疑。隐去此部分代码。想要看的同学可以去力扣搜索。

总结

一道hard难度的算法题。刚拿到题目的时候,很容易陷入日常的思维,使用双指针进行处理。但是双指针的最大问题就是不方便进行具体的区分。此时考虑到二进制的特性,推断出前导0可以忽略不计。因此可以先计算出每个部分的第一个1的位置即可。

总体来说,这道题目的难度适中,之所以被评价为hard难度,一方面是需要考虑的知识点太多,另一方面就是周赛中,能够在有限时间内ac该题目的人数实在太少。

解题证明

image.png