给你一个整数数组 A,只有可以将其划分为三个和相等的非空部分时才返回 true,否则返回 false。
形式上,如果可以找出索引 i+1 < j 且满足 (A[0] + A[1] + … + A[i] == A[i+1] + A[i+2] + … + A[j-1] == A[j] + A[j-1] + … + A[A.length - 1]) 就可以将数组三等分。
示例 1:
输出:[0,2,1,-6,6,-7,9,1,2,0,1]
输出:true
解释:0 + 2 + 1 = -6 + 6 - 7 + 9 + 1 = 2 + 0 + 1
示例 2:
输入:[0,2,1,-6,6,7,9,-1,2,0,1]
输出:false
示例 3:
输入:[3,3,6,5,-2,2,5,1,-9,4]
输出:true
解释:3 + 3 = 6 = 5 - 2 + 2 + 5 + 1 - 9 + 4
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/partition-array-into-three-parts-with-equal-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
bool task(vector<int>& A) {
int size = A.size(); int sum = 0;
for (size_t i = 0; i < size; i++) sum += A[i];
int i = 1;
if (sum % 3 ) return 0; //快速判别给定数组是否合法
else {
sum /= 3; //数组三等分,则每一组之和均为原来的三分之一
int t = A[0]; int count = 0;/组数
while (count < 2 && i < size) {
/*先取前两组,再验证剩余数相加是否为0,若是简单循环count相加会有[10,-10,10,-10,10,
-10,10,-10]这个很尴尬的情况。*/
while (t != sum && i < size)
{
t = t + A[i]; i++;
}
if (t == sum)
{
count++;
if (i < size - 1)//防止数组越界
{
t = A[i];
i++;
}
else if (i == size - 1) {
t = A[i];
if (t==sum)
{
count++;
if (count == 3) return 1;//若i已经在最后了就直接检验
else return 0;
}
}
}
}
if (i < size)//防止[1,-1,1,-1]这种正好两组的情况
{
while (i < size)//从第二组的下一个一直加到最后一个看是否为0
{
t += A[i];
i++;
}
if (t == sum)
{
count++;
}
if (count == 3) return 1;
else return 0;
}
else return 0;//两组直接pass
}
}
leetcode 给出的解答。
int s = accumulate(A.begin(), A.end(), 0);
if (s % 3 != 0) {
return false;
}
int target = s / 3;
int n = A.size(), i = 0, cur = 0;
while (i < n) {
cur += A[i];
if (cur == target) {
break;
}
++i;
}
if (cur != target) {
return false;
}
int j = i + 1;
while (j + 1 < n) { // 需要满足最后一个数组非空
cur += A[j];
if (cur == target * 2) {
return true;
}
++j;
}
return false;
}
/*
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/partition-array-into-three-parts-with-equal-sum/solution/1013-jiang-shu-zu-fen-cheng-he-xiang-deng-de-san-2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。*/
其中用到了accumulate函数,该算法在numeric头文件中定义。对stl容器适合使用。
accumulate(A.begin(), A.end(), 0) 会返回从A的开头加到A的结尾再加0的值。
更为简洁的是,它只要求找到第一个划分点i,然后往后找第二个划分点j,如果在最后一个数之前找到了第二个划分点,就绝对ok,剩下的不空的数组之和必定是sum/3。
而更暴力的一种写法如下:
bool task_3(vector<int>& A) {
int sum = accumulate(A.begin(), A.end(), 0);
if (sum % 3 != 0) {
return false;
}
int count = 0, subSum = 0;
for (int i = 0; i < A.size(); i++) {
subSum += A[i];
if (subSum == sum / 3) {
count++;
subSum = 0;
}
if (count == 3) {
return true;
}
}
return false;
}
/*作者:huwt
链接:https ://leetcode-cn.com/problems/partition-array-into-three-parts-with-equal-sum/solution/jiang-shu-zu-fen-cheng-he-xiang-deng-de-san-ge-b-6/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。*/
虽然对于数组[1,-1,1,-1,1,-1,1,-1]的count是4,但是在3的时候就直接返回了!
结合上述思路,我给出的解的
if (i < size)//防止[1,-1,1,-1]这种正好两组的情况
{
while (i < size)//从第二组的下一个一直加到最后一个看是否为0
{
t += A[i];
i++;
}
if (t == sum)
{
count++;
}
if (count == 3) return 1;
else return 0;
}
为废话,剩下的肯定等于三分之一啊,要不不闹鬼了。于是直接
if (i < size)
{
return 1;
}
else return 0;
即可。
多思考发现规律,别硬写!