Given an array A
of integers, return true
if and only if we can partition the array into three non-empty parts with equal sums.
Formally, we can partition the array if we can find indexes i+1 < j
with (A[0] + A[1] + ... + A[i] == A[i+1] + A[i+2] + ... + A[j-1] == A[j] + A[j-1] + ... + A[A.length - 1])
Example 1:
Input: A = [0,2,1,-6,6,-7,9,1,2,0,1] Output: true Explanation: 0 + 2 + 1 = -6 + 6 - 7 + 9 + 1 = 2 + 0 + 1Example 2:
Input: A = [0,2,1,-6,6,7,9,-1,2,0,1] Output: falseExample 3:
Input: A = [3,3,6,5,-2,2,5,1,-9,4] Output: true Explanation: 3 + 3 = 6 = 5 - 2 + 2 + 5 + 1 - 9 + 4
Constraints:
3 <= A.length <= 50000
-10^4 <= A[i] <= 10^4
将数组分成和相等的三个部分。题意是给你一个整数数组A,只有可以将其划分为三个和相等的非空部分时才返回true,否则返回false。
思路是two pointer。首先判断corner case,如果整个数组中所有元素的加和sum不能被3整除,则一定是false。然后双指针从两边逼近,看左边的leftSum和右边的rightSum是否能都得到1/3的sum。注意双指针while循环的退出条件是(left + 1 < right),如果写成(left < right)会报错,比如如下的case。
Input[1,-1,1,-1]OutputtrueExpectedfalse
时间O(n)
空间O(n) - 用了两个数组存放leftSum和rightSum
Java实现
1 class Solution { 2 public boolean canThreePartsEqualSum(int[] A) { 3 int sum = 0; 4 for (int i : A) { 5 sum += i; 6 } 7 // corner case 8 if (sum % 3 != 0) { 9 // 总和不是3的倍数,直接返回false 10 return false; 11 } 12 13 // 使用双指针,从数组两头开始一起找,节约时间 14 int left = 0; 15 int leftSum = A[left]; 16 int right = A.length - 1; 17 int rightSum = A[right]; 18 19 // 使用left + 1 < right 的原因,防止只能将数组分成两个部分 20 // 例如:[1,-1,1,-1],使用left < right作为判断条件就会出错 21 while (left + 1 < right) { 22 if (leftSum == sum / 3 && rightSum == sum / 3) { 23 // 左右两边都等于 sum/3 ,中间也一定等于 24 return true; 25 } 26 if (leftSum != sum / 3) { 27 // left = 0赋予了初值,应该先left++,在leftSum += A[left]; 28 leftSum += A[++left]; 29 } 30 if (rightSum != sum / 3) { 31 // right = A.length - 1 赋予了初值,应该先right--,在rightSum += A[right]; 32 rightSum += A[--right]; 33 } 34 } 35 return false; 36 } 37 }
JavaScript实现
1 /** 2 * @param {number[]} A 3 * @return {boolean} 4 */ 5 var canThreePartsEqualSum = function (A) { 6 let sum = 0; 7 for (num of A) { 8 sum += num; 9 } 10 11 // corner case 12 if (sum % 3 !== 0) { 13 return false; 14 } 15 16 // normal case 17 let left = 0; 18 let leftSum = A[left]; 19 let right = A.length - 1; 20 let rightSum = A[right]; 21 while (left + 1 < right) { 22 if (leftSum === sum / 3 && rightSum === sum / 3) { 23 // 左右两边都等于 sum/3 ,中间也一定等于 24 return true; 25 } 26 if (leftSum !== sum / 3) { 27 // left = 0赋予了初值,应该先left++,在leftSum += A[left]; 28 leftSum += A[++left]; 29 } 30 if (rightSum !== sum / 3) { 31 // right = A.length - 1 赋予了初值,应该先right--,在rightSum += A[right]; 32 rightSum += A[--right]; 33 } 34 } 35 return false; 36 };