defsplitArraySameAverage(self,A: List[int]) ->bool: n =len(A) avg =sum(A)/ nfor i inrange(1, n //2+1):for s incombinationSum(A, i):ifabs(s - avg * i)<1e-6:returnTruereturnFalse
但是遗憾的是,这仍然不足以通过所有的测试用例。
接下来,我们可以通过进一步剪枝的手段来达到 AC 的目的。 很多回溯的题目都是基于剪枝来完成的。剪枝是回溯问题的核心考点。
具体地,我们可以 combinationSum A 数组的一半(不妨称 A1),然后 combinationSum A 数组的令一半(不妨称 A2),那么 A1 和 A2 的总和如果是 avg * i 不也行么?简单起见,我们可以令 A1 为数组 A 的前一半, A2 为数组的后一半。
同时,为了避免这种加法,我们可以对问题进行一个转化。即将数组 A 的所有数都减去 avg,这样问题转化为找到一个和为 0 的组合,即可以找到一个和为 avg * i 的组合。
关键点
双端搜索
代码
语言支持:Python3
Python3 Code:
classSolution(object):defsplitArraySameAverage(self,A):from fractions import Fraction N =len(A) total =sum(A) A = [a -Fraction(total, N)for a in A] # 转化后的 A,免于计算 sumif N ==1:returnFalse S1 =set()# 所有 B 可能的和的集合for i inrange(N//2):# {a + A[i] for a in S1} 在之前选择的基础上选择 A[i] 的新集合# {A[i]} 是仅选择 A[i] 的新集合# S1 是不选择 A[i] 的集合# | 是集合并操作 S1 ={a + A[i]for a in S1}| S1 |{A[i]}if0in S1:returnTrue S2 =set()# 所有 C 可能的和的集合for i inrange(N//2, N): S2 ={a + A[i]for a in S2}| S2 |{A[i]}if0in S2:returnTrue# 如果 S1 和 S2 都没有和为 0 的组合。那么我们就需要从 S1 和 S2 分别找一个 a 和 b,看其和是否能达到 0. 如果可以,说明也能满足题意# 为了避免 B 或者 C 为空,我们增加一个这样的判断: (ha, -ha) != (sleft, sright) sleft =sum(A[i] for i inrange(N//2)) sright =sum(A[i] for i inrange(N//2, N))returnany(-ha in S2 and (ha, -ha) != (sleft, sright) for ha in S1)