b_lc_通过最少操作次数使数组的和相等(贪心)

A和B两个数组中的所有值都在[1,6]。每次操作中,你可以选择 任意 数组中的任意一个整数,将它变成 1 到 6 之间 任意 的值(包含 1 和 6)。请返回使 A中所有数的和与 B 中所有数的和相等的最少操作次数。无解返回 -1 。

思路:约定sum(A)<sum(B),sA∈[n,6n],sA∈[m,6m]:

  • 有解则,sA和sB有交集,也就是 6n<=m
  • 否则无解
class Solution:
    def minOperations(self, A: List[int], B: List[int]) -> int:
        def get(x, m: List[int]): #得到距离x需要的操作次数
            s, ans = 0, 0
            for i in range(1,7): s += i * m[i]
            d = abs(x - s)
            if s < x:
                for i in range(1,6):
                    a = 6 - i
                    if a * m[i] >= d: return ans + math.ceil(d / a)
                    ans, d = ans + m[i], d - a * m[i]
            else:
                for i in range(6,1,-1):
                    a = i - 1
                    if a * m[i] >= d: return ans + math.ceil(d / a)
                    ans, d = ans + m[i], d - a * m[i]
            return ans

        n, m = len(A), len(B)
        if n > m: return self.minOperations(B, A)
        if 6*n < m: return -1
        m1, m2 = [0]*7, [0]*7
        for x in A: m1[x] = m1[x] + 1
        for x in B: m2[x] = m2[x] + 1
        ans = float('inf')
        for x in range(m, 6*n+1):
            ans = min(ans, get(x, m1) + get(x, m2))
        return ans

其实 get 函数可以用逻辑优化掉的...

posted @ 2021-03-02 11:12  童年の波鞋  阅读(158)  评论(0编辑  收藏  举报