Leetcode_Ex2: 数组之和三等分问题
1. 问题描述
该问题是leetcode上一道难易程度为easy的题目,原题如下:
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])
Example1
Input: [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: [0,2,1,-6,6,7,9,-1,2,0,1]
Output: false
Example 3
Input: [3,3,6,5,-2,2,5,1,-9,4]
Output: true
Explanation: 3 + 3 = 6 = 5 - 2 + 2 + 5 + 1 - 9 + 4
给定一个整数数组,如果该数组可以被分为三个不为空的子数组,且三个数组的和相等,则满足要求,否则不满足要求。如:数组为[0,2,1,-6,6,-7,9,1,2,0,1],则可以分为数组[0, 2, 1]、[-6, 6, -7, 9]和[2, 0, 1],它们的和均为3。
2. 简单方法
针对该问题,我们很容易利用双重循环来实现,设定两个循环地址变量i和j,遍历i和j的组合,找到????A[0:i]和A[i:j]及A[j:]相等的i和j即可,复杂度为O(n^2),示例代码如下:
class Solution(object):
def canThreePartsEqualSum(self, A):
"""
:type A: List[int]
:rtype: bool
"""
array_sum = sum(A)
if array_sum % 3 != 0:
return False
else:
divide = array_sum / 3
current_sum = 0
ids = []
for i in range(len(A)):
current_sum += A[i]
if current_sum == divide:
current_sum = 0
ids.append(i)
if len(ids) == 3:
return True
else:
return False
当针对Leetcode提供的较大的测试样例时,该代码运行速度较慢,提示"Time Limit Exceeded"。
3. 是否存在O(n)的算法?
让我们再来回顾一下问题:是否存在一种切分,得到三个和相等的子数组,略懂算法的小明说,他一定会这样做:
- 先计算出数组的总和array_sum,如果可以分为三部分,则一定可以被3整除,记为divide;
- 我沿着数组走,边走边记录当前的和到current_sum,如果达到了divide,就把当前数组id记录下来,把current_sum置为0;
- 继续前行,直到走到结尾。最后小明看看记了几个id,如果等于3个,不就表明可以分为3部分吗?
小明的方法不就是动态规划的最简版本吗,按着这个想法,python代码如下:
class Solution(object):
def canThreePartsEqualSum(self, A):
"""
:type A: List[int]
:rtype: bool
"""
array_sum = sum(A)
if array_sum % 3 != 0:
return False
else:
divide = array_sum / 3
current_sum = 0
ids = []
for i in range(len(A)):
current_sum += A[i]
if current_sum == divide:
current_sum = 0
ids.append(i)
if len(ids) == 3:
return True
else:
return False
这次我们再次提交,Leetcode给出了Accepted的提示,表明已经被认可了!
4. Go Go Go! 会更快吗?
抱着试试的态度,我们用Go语言重写了这个小代码,让我们看看Go的表现:
package main
import "fmt"
func partThreeArray(A []int) bool {
var flag bool
array_sum := sum_array(A)
if array_sum % 3 != 0 {
flag = false
} else {
divide := array_sum/3
current_sum := 0
count := 0
for i := 0; i < len(A); i++{
current_sum += A[i]
if current_sum == divide {
current_sum = 0
count += 1
}
}
if count == 3 {
flag = true
}
}
return flag
}
func sum_array(A []int) int {
var sum int
size := len(A)
for i:=0; i<size; i++ {
sum += A[i]
}
return sum
}
这里我们定义了两个子函数,其中sum_array用于计算数组的和,经过瞬间的等待,Leetcode返回给了我们结果:
可以看到,时间消耗快于100%的提交,空间占用小于100%的提交,Go Go Go!