Leetcode daily 20/03/11 将数组分成和相等的三个部分
将数组分成和相等的三个部分
-题目-
给你一个整数数组 A,只有可以将其划分为三个和相等的非空部分时才返回 true,否则返回 false。
形式上,如果可以找出索引 i+1 < j 且满足 (A[0] + A[1] + ... + A[i] == A[i+1] + A[i+2] + ... + A[j-1] == A[j] + A[j-1] + ... + A[A.length - 1]) 就可以将数组三等分。
-示例 1-
输入:[0,2,1,-6,6,-7,9,1,2,0,1]
输出:true
解释:0 + 2 + 1 = -6 + 6 - 7 + 9 + 1 = 2 + 0 + 1
-示例 2-
输入:[0,2,1,-6,6,7,9,-1,2,0,1]
输出:false
-示例 3-
输入:[3,3,6,5,-2,2,5,1,-9,4]
输出:true
解释:3 + 3 = 6 = 5 - 2 + 2 + 5 + 1 - 9 + 4
-方法1(超时)-
把数组A分成三部分: A[:i]
、A[i:j]
、A[j:]
,使这三部分的和相等即可。
-代码-
class Solution:
def canThreePartsEqualSum(self, A: List[int]) -> bool:
for i in range(1, len(A)):
for j in range(i + 1, len(A)):
if sum(A[:i]) == sum(A[i:j]) == sum(A[j:]):
return True
return False
-复杂度-
- \(T(n) = O(n^2)\) (遍历数组 * 每次判断的求和)
- \(S(n) = O(1)\)
-方法1 笔记-
- 外循环下标应该从1开始,以便[:i]从第一个元素开始取值。
-方法2-
符合条件的数组必定能被3整除。(但能被3整除的数组不一定符合条件!如示例 2)。只要前两部分的和分别和数组和的 \(\frac{1}{3}\) 相等即可。
算法:
- 计算数组和
sum_A
。 - 如果
sum_A
不能被3整除,返回False。 - 计算数组和的 \(\frac{1}{3}\) :
sum_A_one_third
- 遍历数组,下标为
i
:- 如果
A[:i]
的和为sum_A_one_third
,找到第一个数组片段。- 从
i + 1
开始遍历数组,下标为j
:- 如果
A[i:j]
的和为sum_A_one_third
,找到第二个数组片段。返回True。
- 如果
- 从
- 如果
- 循环之后未找到符合条件的三个数组片段,返回False。
-ac代码-
class Solution:
def canThreePartsEqualSum(self, A: List[int]) -> bool:
sum_A = sum(A)
if sum_A % 3 != 0:
return False
sum_A_one_third = sum_A / 3
for i in range(1, len(A)):
if sum(A[:i]) == sum_A_one_third:
for j in range(i + 1, len(A)):
if sum(A[i:j]) == sum_A_one_third:
return True
return False
-复杂度-
- \(T(n) = O(n)\)?
- \(S(n) = O(1)\)
-方法2 笔记-
range(1, len(A))
保证第一个片段不为空,[i:j]
保证第三个片段不为空。
-方法2·改-
用变量sum_i
和sum_j
存储数组第一个片段和第二个片段的和,而不是每次都用sum()
求和,大大缩短所需时间。
-ac代码-
class Solution:
def canThreePartsEqualSum(self, A: List[int]) -> bool:
sum_A = sum(A)
if sum_A % 3 != 0:
return False
sum_A_one_third = sum_A / 3
sum_i = 0 # stores the sum of the first slice
for i in range(0, len(A) - 2):
sum_i += A[i] # updates the sum of the first slice
if sum_i == sum_A_one_third:
sum_j = 0 # stores the sum of the second slice
for j in range(i + 1, len(A) - 1):
sum_j += A[j] # updates the sum of the second slice
if sum_j == sum_A_one_third:
return True
return False
-复杂度-
- \(T(n) = O(n)\)
- \(S(n) = O(1)\)
-方法2·改 笔记-
- 外循环遍历到倒数第三个元素,内循环遍历到倒数第二个元素,分别保证第一个、第二个片段不为空。
-笔记-
- 算法-笔记:计算复杂度考虑内置函数。
- 算法-笔记:两个
for
的时间复杂度也可能是\(O(n)\),如方法2。