[LeetCode每日1题][简单] 1013. 将数组分成和相等的三个部分

题目

1013. 将数组分成和相等的三个部分 - 力扣(LeetCode)
在这里插入图片描述

前缀和解法

思路

  1. 遍历数组,并维护一个前缀和数组preSum,方便后面求区间和
  2. 数组和sum = preSum[size]-1
  3. 如果sum%3 != 0 返回false
  4. 遍历preSum,寻找preSum[i] == sum/3,如果i不存在,返回false
  5. 从后往前遍历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)

参考

【将数组分成和相等的三个部分】:简洁的C++ - 将数组分成和相等的三个部分 - 力扣(LeetCode)

原文地址:https://www.cnblogs.com/zaynq/p/12679079.html