题目
1013. 将数组分成和相等的三个部分 - 力扣(LeetCode)
前缀和解法
思路
- 遍历数组,并维护一个前缀和数组
preSum
,方便后面求区间和 - 数组和
sum = preSum[size]-1
- 如果
sum%3 != 0
返回false
- 遍历
preSum
,寻找preSum[i] == sum/3
,如果i
不存在,返回false
- 从后往前遍历
preSum
求后缀和,寻找preSum[size-1]-preSum[j] == sum/3
,如果j
存在,返回true
复杂度分析
遍历一次原数组和前缀和数组,时间复杂度O(n)
多使用了一个前缀和数组,空间复杂度O(n)
实现
class Solution {
public:
bool canThreePartsEqualSum(vector<int>& A) {
int size = A.size();
if(size<3) return false;
vector<int> preSum;
preSum.push_back(A[0]);
for(int i=1;i<size;i++) {
preSum.push_back(preSum[i-1]+A[i]);
}
int lastIndex = size-1;
int sum = preSum[lastIndex]/3;
if(preSum[lastIndex]%3 != 0) return false;
int ii = -1;
for(int i=0;i<size;i++) {
if(preSum[i] == sum) {
ii = i;
break;
}
}
if(ii == -1) return false;
int jj = -1;
for(int i=lastIndex-1;i>ii;i--) {
if(preSum[lastIndex]-preSum[i] == sum) {
jj = i;
break;
}
}
return jj!=-1;
}
};
优化
可以不用前缀和数组,优化空间复杂度到O(1):
先求出数组的和sum
,然后再次遍历求和curSum
,遇到sum/3
,则k++
,curSum = 0
,最后返回k==3
。
由于还是遍历了两次,时间复杂度和前缀和解法一致。
class Solution {
public:
bool canThreePartsEqualSum(vector<int>& A) {
int sum = 0, currSum = 0, k = 0;
for(auto it : A)
sum += it;
if(sum % 3 != 0)
return false;
for(auto it : A)
{
currSum += it;
if(currSum == sum / 3){
currSum = 0;
k++;
}
}
if(currSum == sum / 3)
k++;
return k==3;
}
};
C++复习
- 二分查找
bool binary_search(arr.begin(), arr.end(), target)
- 累计求和
int accumulate(arr.begin(), arr.end(), initVal)