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_isum_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。
posted @ 2020-03-11 13:51  Sola~  阅读(159)  评论(0编辑  收藏  举报