805. Split Array With Same Average
阿新 • • 發佈:2019-01-13
解法
解法一:轉化成是否存在k個數使得和為target
很明顯,B和C那相等的均值一定是A的均值
所以給定B的長度l,我們可以計算出B的總和應該是
所以問題就轉化成數組裡是不是有l個數的和加起來剛好等於這個值,dfs求解
但是會超時,需要剪下枝:
- 如果所有候選的數加起來也組不夠target,pass
- 如果前一個數為a,它失敗了,這個數也是a,那也不用遍歷【瞬間快了】
class Solution(object):
def splitArraySameAverage(self, A):
"""
:type A: List[int]
:rtype: bool
"""
A.sort()
n = len(A)
total = sum(A)
P = [0] * n
P[ 0] = A[0]
for i, a in itertools.islice(enumerate(A), 1, None):
P[i] = P[i - 1] + a
def check(i, l, target):
if i == -1:
return l == 0 and target == 0
if l == 0:
return target == 0
if target < 0:
return False
if target > P[i]:
return False
for j in xrange(i, l - 2, -1):
if (j==i or A[j]!=A[j+1]) and check(j - 1, l - 1, target - A[j]):
return True
return False
for l in xrange(1, n // 2 + 1):
if total * l % n == 0 and check(n - 1, l, total * l / n):
return True
return False
解法二:中間相遇
我覺得大概這種和剛好等於多少多少的型別都可以用中間相遇來解
但是由於B的均值是確定的,但是和不一定,如何得到B的固定的和呢?
我們把A裡的每個數都減去平均值aver
,那麼A的均值就變成了0,B的均值也是0,和就也固定為0了
使用中間相遇法,把陣列分成左右兩部分,如果左邊有和為x
並且右邊為-x
,那麼把兩部分的陣列拿起來就可以拼成B了
這裡有兩個需要注意的:
- x和-x不能剛好用了全部左右全部的數字,否則C會是空的
- 但是如果只用某一邊的數字就可以湊成0了,那麼就不用再考慮後面的了
class Solution(object):
def splitArraySameAverage(self, A):
"""
:type A: List[int]
:rtype: bool
"""
from fractions import Fraction
n = len(A)
total = sum(A)
A = [a-Fraction(total,n) for a in A]
if n==1:
return False
AL = A[:n//2]
AR = A[n//2:]
def all_sums(lis):
res = set()
for a in lis:
new = set()
new.add(a)
for num in res:
new.add(num+a)
res |= new
return res
left = all_sums(AL)
if 0 in left:
return True
right = all_sums(AR)
if 0 in right:
return True
sum_left = sum(AL)
sum_right = sum(AR)
return any(-x in right and (x,-x)!=(sum_left,sum_right) for x in left)