题目描述
给定一个由 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] 为第三部分。这三个部分所表示的二进制值相等。
如果无法做到,就返回 [-1, -1]。
注意,在考虑每个部分所表示的二进制时,应当将其看作一个整体。例如,[1,1,0] 表示十进制中的 6,而不会是 3。此外,前导零也是被允许的,所以 [0,1,1] 和 [1,1] 表示相同的值。
解题思路
- 主要思路是将给定的数组分为三个部分,确定固定区间的值,若不符合要求则返回 [-1, -1]。
- 优化点一:统计数组中 1 的个数,如果不是 3 的倍数,不符合题目要求,直接返回 [-1, -1]。
- 优化点二:如果 1 的个数为 0 且数组长度至少为 3,可直接返回 [0, 2]。
- 找到三个部分中每一个 1 开始的位置,以此隔离区间。
- 确定好三个部分后,由于最后一个部分到数组末尾的位置是确定的,反向确定第一个和第二个部分。通过循环逐位比较,若有不相等则返回 [-1, -1],否则返回符合要求的位置。
代码实现
class Solution {
public int[] threeEqualParts(int[] arr) {
// 统计数组中 1 的个数
int sum = Arrays.stream(arr).sum();
// 如果 1 的个数不能被 3 整除
if (sum % 3 != 0) {
return new int[]{-1, -1};
}
// 如果 sum 的和为 0,直接返回
if (sum == 0) {
return new int[]{0, 2};
}
// 将数组划分为三个部分,每部分应包含的 1 的数量
int partial = sum / 3;
// 分别去确定三个区间的开始位置
int , second = , third = , cur = ;
( ; i < arr.length; i++) {
(arr[i] == ) {
(cur == ) {
first = i;
} (cur == partial) {
second = i;
} (cur == * partial) {
third = i;
}
cur++;
}
}
arr.length - third;
(first + len <= second && second + len <= third) {
;
(third + i < arr.length) {
(arr[first + i] != arr[second + i] || arr[first + i] != arr[third + i]) {
[]{-, -};
}
i++;
}
[]{first + len - , second + len};
}
[]{-, -};
}
}

