548. Split Array with Equal Sum
Given an array with n integers, you need to find if there are triplets (i, j, k) which satisfies following conditions:
0 < i, i + 1 < j, j + 1 < k < n - 1
Sum of subarrays (0, i - 1), (i + 1, j - 1), (j + 1, k - 1) and (k + 1, n - 1) should be equal.
where we define that subarray (L, R) represents a slice of the original array starting from the element indexed L to the element indexed R.
Example:
Input: [1,2,1,2,1,2,1]
Output: True
Explanation:
i = 1, j = 3, k = 5.
sum(0, i - 1) = sum(0, 0) = 1
sum(i + 1, j - 1) = sum(2, 2) = 1
sum(j + 1, k - 1) = sum(4, 4) = 1
sum(k + 1, n - 1) = sum(6, 6) = 1
Note:
- 1 <= n <= 2000.
- Elements in the given array will be in range [-1,000,000, 1,000,000].
方法1: presum + brute force,TLE
思路:
枚举,虽然tle,但是这个思路是一定要先给出的,而且时间复杂度要会算,三个循环O(n^3)。
Complexity
Time complexity: O(n^3)
Space complexity: O(n)
class Solution1 {
public:
bool splitArray(vector<int>& nums) {
int n = nums.size();
if (n < 7) return false;
vector<int> presum(n, 0);
presum[0] = nums[0];
for (int i = 1; i < nums.size(); i++) {
presum[i] = presum[i - 1] + nums[i];
}
// 枚举所有第一个轴点
for(int i = 1; i < nums.size() - 5; i++) {
int sum1 = presum[i - 1];
// 枚举所有第二个轴点
for (int j = i + 2; j < nums.size() - 3; j++) {
int sum2 = presum[j - 1] - presum[i];
// 枚举所有第三个轴点
if (sum1 != sum2) continue;
for (int k = j + 2; k < nums.size() - 1; k++) {
int sum3 = presum[k - 1] - presum[j];
int sum4 = presum[nums.size() - 1] - presum[k];
if (sum1 == sum2 && sum2 == sum3 && sum3 == sum4)
return true;
}
}
}
return false;
}
};
方法2: presum + hash
思路:
先确定中间的轴点,然后尝试分别切分左半边和右半边。因为我们知道要四个部分都相等,首先各自要切分出相等的两份,这样就淘汰了大部分瞎切的情况,剩下的各自相等的情况,用hashset来迅速筛选出与左半部分先得出的可能性也相等的解,就可以保证四个部分连等。这样时间复杂度降到了O(n^2), 只嵌套两个循环,且可以左右在同一个循环内完成。
Complexity
Time complexity: O(n^2)
Space complexity: O(n)
class Solution {
public:
bool splitArray(vector<int>& nums) {
int n = nums.size();
if (n < 7) return false;
vector<int> presum(n, 0);
presum[0] = nums[0];
for (int i = 1; i < n; i ++) {
presum[i] = presum[i - 1] + nums[i];
}
// 枚举第二个轴点
for (int j = 3; j < n - 3; j ++) {
unordered_set<int> hash;
// 尝试切分左半段
for (int i = 1; i < j - 1; i++) {
if (presum[i - 1] == presum[j - 1] - presum[i])
hash.insert(presum[i - 1]);
}
// 尝试切分右半段
for (int k = j + 2; k < n - 1; k++) {
if (presum[n - 1] - presum[k] == presum[k - 1] - presum[j] && hash.count(presum[n - 1] - presum[k]))
return true;
}
}
return false;
}
};