一、题目
给定一个由 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]
为第三部分;- 这3个部分所表示的二进制值相等;
如果无法做到,就返回 [-1, -1]
。
注意,在考虑每个部分所表示的二进制时,应当将其看作一个整体。例如,[1,1,0]
表示十进制中的 6
,而不会是 3
。此外,前导零也是被允许的,所以 [0,1,1]
和 [1,1]
表示相同的值。
二、示例
2.1> 示例 1:
【输入】arr = [1,0,1,0,1]
【输出】[0,3]
2.2> 示例 2:
【输入】arr = [1,1,0,1,1]
【输出】[-1,-1]
2.3> 示例 3:
【输入】arr = [1,1,0,0,1]
【输出】[0,2]
提示:
-
3
<= arr.length <=3 * 10^4
-
arr[i] 是
0
或1
三、解题思路
根据题目描述,我们可以知道要将arr数组分成3份,并且对于这3份由0
和1
组成的二进制值要相同。因为是二进制,由0和1组成,所以,如果二进制相同的话,那么这3个分组中,1的个数一定是相同的。所以,以下图为例,我们统计出了一共有3个“1”,满足被3整除。所以,第一个条件就满足了。
“1”我们校验完毕之后,我们再来看看“0”。对于二进制来说,影响最终结果的其实是“1”后面的“0”的个数,(即:00010
和00000010
是相等的,但是0010
和001000
就是不等的了)。那么我们可以推导出在arr
数组中最后的那个“1”,它后面有多少个“0”,那么每个分组中的最后那个“1”后面就必须有相同数量的“0”。我们还是以下图为例,由于arr[7]
是最后一个“1”,它后面只有1个“0”,那么根据上面我们描述的规律,就可以将数组 arr = [0,0,1,0,1,0,0,1,0]
拆分为[0,0,1,0]
、[1,0]
和[0,1,0]
。
然后,我们以最短分组长度为基准,从末尾开始校验每组中相对应位置的值是否相同,如果都相同,那么就满足了题目中所描述的“三等分”了。然后将[i, j]
返回即可。

四、代码实现
class Solution {
public int[] threeEqualParts(int[] arr) {
// 用于记录每个“1”所在arr中的位置(index)
int[] record = new int[arr.length + 1];
int oneCount = 0;
for (int i = 0; i < arr.length; i++) if (arr[i] == 1) record[++oneCount] = i;
// 如果数组全是0的情况,固定返回[0, arr.length - 1]
if (oneCount == 0) return new int[]{0, arr.length - 1};
// 如果1的个数不能被平分,则表示无法平均分配
if (oneCount % 3 != 0) return new int[]{-1, -1};
// gn:每组1的个数 lzn:最后一组末尾0的个数
int gn = oneCount / 3, lzn = arr.length - 1 - record[oneCount];
// 如果每组末尾0的个数不足,则返回[-1,-1]
if (record[gn * 2] - record[gn] < lzn || record[gn * 3] - record[gn * 2] < lzn) return new int[]{-1, -1};
int tail1 = record[gn] + lzn, tail2 = record[gn * 2] + lzn, tail3 = record[gn * 3] + lzn,
nums = Math.min(Math.min(tail1 + 1, tail2 - tail1), tail3 - tail2);
int[] result = new int[]{tail1, tail2 + 1};
while(nums-- > 0) {
if (arr[tail1] != arr[tail2] || arr[tail1]!= arr[tail3] || arr[tail2] != arr[tail3]) return new int[]{-1, -1};
tail1--; tail2--; tail3--;
}
return result;
}
}

今天的文章内容就这些了:
写作不易,笔者几个小时甚至数天完成的一篇文章,只愿换来您几秒钟的 点赞 & 分享 。
更多技术干货,欢迎大家关注公众号“爪哇缪斯” ~ \(o)/ ~ 「干货分享,每天更新」
网友评论