[LeetCode] 1013. Partition Array Into Three Parts With Equal Sum

将数组分成和相等的三个部分。题意是给你一个整数数组 A,只有可以将其划分为三个和相等的非空部分时才返回 true,否则返回 false。例子,

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 + 1

Example 2:

Input: A = [0,2,1,-6,6,7,9,-1,2,0,1]
Output: false

Example 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

思路是用双指针做。首先判断corner case,如果整个数组中所有元素的加和sum不能被3整除,则一定是false。然后双指针从两边逼近,看左边的leftSum和右边的rightSum是否能都得到1/3的sum。注意双指针while循环的退出条件是(left + 1 < right),如果写成(left < right)会报错,比如如下的case。

Input
[1,-1,1,-1]
Output
true
Expected
false

时间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 };

猜你喜欢

转载自www.cnblogs.com/aaronliu1991/p/12461640.html