You are given an array arr
which consists of only zeros and ones, divide the array into three non-empty parts such that all of these parts represent the same binary value.
If it is possible, return any [i, j]
with i + 1 < j
, such that:
arr[0], arr[1], ..., arr[i]
is the first part,arr[i + 1], arr[i + 2], ..., arr[j - 1]
is the second part, andarr[j], arr[j + 1], ..., arr[arr.length - 1]
is the third part.- All three parts have equal binary values.
If it is not possible, return [-1, -1]
.
Note that the entire part is used when considering what binary value it represents. For example, [1,1,0]
represents 6
in decimal, not 3
. Also, leading zeros are allowed, so [0,1,1]
and [1,1]
represent the same value.
Example 1:
Input: arr = [1,0,1,0,1] Output: [0,3]
Example 2:
Input: arr = [1,1,0,1,1] Output: [-1,-1]
Example 3:
Input: arr = [1,1,0,0,1] Output: [0,2]
Constraints:
3 <= arr.length <= 3 * 104
arr[i]
is0
or1
不得不说其实很讨厌做这种题, 不是说思考的时候有多难,而是实现的时候要像放贼一样防着各种特殊情况。
整体思路是如果一个数组可以被分成三个相等的部分,那一定要满足以下3个条件:
1. 整个数组里的1的数量一定是3的倍数, 且分到每个部分里面1的数量一定是一样的
2. 每个部分里面从第一个1到最后一个1这个切片,每个部分都是一样的
3. 每个部分的后缀0的数量一定与最后一部分的后缀0的数量是一致的
三个条件全部满足则能分,有一个不满足则不能分。
具体的方法是把数组分成几个部分, 下面来个例子:
[0 --- 0 --- 0 --- 1 --- 0 --- 1 --- 0 --- 0 --- 0 --- 1 --- 0 --- 1 --- 0 --- 0 --- 0 --- 1 --- 0 --- 1 --- 0 --- 0 ---0]
| | | | | |
S1---------E1 S2--------E2 S3---------E3
|-----F1-----| |-----F2---| |-----F3----|
不会画图,大家凑或着看吧。Fi为每一部分从第一个1到最后一个1的切片, Si为Fi的起始索引, Ei为Fi的终止索引。F1、F2、F3这三段一定是完全一样的。然后再来看后置0的情况, 因为前置0没有意义所以我们可以任意分割Fi之间的0, 以保证前段后置0达到我们所需的数量。但是首先我们得看到, 从E3到数组结尾的0, 也就是F3的后置0的数量我们是没法改变的, 也就是说前面F1、F2的后置0的数量一定要有能力能跟F3的后置0的数量一致,我们才能把数组'等分'。但就像我们前面所说的,前置0没有意义,而中间的那些0段我们可以任意分割成两段, 前半段作为Fi的后置0,后半段作为Fi+1的前置0, 所以我们可以得出, 只要E1到S2之间的0的数量和E2到S3之间的0的数量大于等于E3到数组末尾的0的数量就可以实现'等分'。但是这里面要考虑数组全都是0的情况和有3个1的情况, 这两种情况单独处理一下就好。
具体实现如下(Rust):
impl Solution {
pub fn three_equal_parts(arr: Vec<i32>) -> Vec<i32> {
let ones = arr.iter().filter(|&&v| v == 1).count();
if ones == 0 {
return vec![0, arr.len() as i32 - 1];
}
if ones % 3 != 0 {
return vec![-1, -1];
}
let factor = ones / 3;
let (mut s1, mut e1, mut s2, mut e2, mut s3, mut e3) = (0, 0, 0, 0, 0, 0);
let mut count = 0;
for i in 0..arr.len() {
if arr[i] == 1 {
count += 1;
match count {
1 => {
s1 = i;
if factor == 1 {
e1 = i;
}
}
c if c == factor => e1 = i,
c if c == factor + 1 => {
s2 = i;
if factor == 1 {
e2 = i;
}
}
c if c == factor * 2 => e2 = i,
c if c == factor * 2 + 1 => {
s3 = i;
if factor == 1 {
e3 = i;
}
}
c if c == factor * 3 => e3 = i,
_ => {}
}
}
}
for ((v1, v2), v3) in arr[s1..e1 + 1]
.iter()
.zip(arr[s2..e2 + 1].iter())
.zip(arr[s3..e3 + 1].iter())
{
if v1 != v2 || v2 != v3 {
return vec![-1, -1];
}
}
let tail_zero = arr.len() - 1 - e3;
if s2 - e1 - 1 < tail_zero || s3 - e2 - 1 < tail_zero {
return vec![-1, -1];
}
vec![(e1 + tail_zero) as i32, (e2 + tail_zero + 1) as i32]
}
}