题目地址:
https://leetcode.com/problems/partition-array-into-three-parts-with-equal-sum/
给定一个数组 A A A,问是否能将 A A A拆成 3 3 3段,使得每段非空,并且每段数字和相等。
先求一下 A A A的数字和 s s s,则每段的数字和应当为 s / 3 s/3 s/3。如果 s s s不能被 3 3 3整除那直接返回false。接下来开始截取 A A A中和为 s / 3 s/3 s/3的一段,并对段数进行计数,设最终计数为 c c c。如果 c = 3 c=3 c=3或者 s = 0 s=0 s=0并且 c ≥ 3 c\ge 3 c≥3,就说明可以拆成和相等的 3 3 3段,返回true,否则返回false。
算法正确性证明:
首先算法返回true,则
A
A
A一定能拆成和相等的
3
3
3段,这一点很显然。如果算法返回false,但
A
A
A仍然可以拆成和相等的
3
3
3段,如果
s
=
0
s=0
s=0,那么算法得到的
c
≥
3
c\ge 3
c≥3,应该返回了true,矛盾;如果
s
≠
0
s\ne 0
s=0,首先算法算出的
c
c
c一定满足
c
≥
3
c\ge 3
c≥3,如果
c
>
3
c>3
c>3,那么说明存在超过
3
3
3段的子段和等于
s
/
3
s/3
s/3,则
A
A
A总和应该等于
c
s
/
3
≠
s
cs/3\ne s
cs/3=s矛盾,所以
c
=
3
c=3
c=3,应该返回true,矛盾。所以算法正确。
代码如下:
public class Solution {
public boolean canThreePartsEqualSum(int[] A) {
int sum = 0;
for (int i = 0; i < A.length; i++) {
sum += A[i];
}
if (sum % 3 != 0) {
return false;
}
int curSum = 0, count = 0;
for (int i = 0; i < A.length; i++) {
curSum += A[i];
if (curSum == sum / 3) {
count++;
curSum = 0;
}
}
return count == 3 || (sum == 0 && count >= 3);
}
}
时间复杂度 O ( n ) O(n) O(n),空间 O ( 1 ) O(1) O(1)。