1. 程式人生 > >805. Split Array With Same Average

805. Split Array With Same Average

解法

解法一:轉化成是否存在k個數使得和為target

很明顯,B和C那相等的均值一定是A的均值
所以給定B的長度l,我們可以計算出B的總和應該是 s u m ( A

) l n \frac{sum(A)*l}{n}
所以問題就轉化成數組裡是不是有l個數的和加起來剛好等於這個值,dfs求解
但是會超時,需要剪下枝:

  1. 如果所有候選的數加起來也組不夠target,pass
  2. 如果前一個數為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了
這裡有兩個需要注意的:

  1. x和-x不能剛好用了全部左右全部的數字,否則C會是空的
  2. 但是如果只用某一邊的數字就可以湊成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)