LeetCode 465 - Optimal Account Balancing - Hard (Python)

A group of friends went on holiday and sometimes lent each other money. For example, Alice paid for Bill's lunch for $10. Then later Chris gave Alice $5 for a taxi ride. We can model each transaction as a tuple (x, y, z) which means person x gave person y $z. Assuming Alice, Bill, and Chris are person 0, 1, and 2 respectively (0, 1, 2 are the person's ID), the transactions can be represented as [[0, 1, 10], [2, 0, 5]].

Given a list of transactions between a group of people, return the minimum number of transactions required to settle the debt.

Note:

  1. A transaction will be given as a tuple (x, y, z). Note that x ≠ y and z > 0.
  2. Person's IDs may not be linear, e.g. we could have the persons 0, 1, 2 or we could also have the persons 0, 2, 6.

Example 1:

Input:
[[0,1,10], [2,0,5]]

Output:
2

Explanation:
Person #0 gave person #1 $10.
Person #2 gave person #0 $5.

Two transactions are needed. One way to settle the debt is person #1 pays person #0 and #2 $5 each.

Example 2:

Input:
[[0,1,10], [1,0,1], [1,2,5], [2,0,5]]

Output:
1

Explanation:
Person #0 gave person #1 $10.
Person #1 gave person #0 $1.
Person #1 gave person #2 $5.
Person #2 gave person #0 $5.

Therefore, person #1 only need to give person #0 $4, and all debt is settled.

思路:对交易而言,如果有n笔交易可以构成一个环,那么n笔交易可以简化为n-1笔。比如(a给b25元,b给c25元,c给a50元。那么这个环是3笔,可以简化为2笔,b给a25元以及c给a25元。注意,成环
还要求环的总和为0)所以如果形成一个环,交易就可以减少一笔。为了最小化交易数量,我们的目标就转化为最大化可以成环的个数。

步骤:1 计算出每一个人的净额。整数表示这个人要还多少钱,负数表示这个人可以收多少钱。用net数组来记录每一个人的净额。假设我们得到的数组为[25, -50, 40, 10, -40, -10, 25]
2 从net[0]开始进行bfs搜索。q中加入的起始值为(net[0], [0], 1) 所对应的我们想要搜索的值为cur(当前的sum值), path, start.
3 进入bfs,跳出条件为当cur==0, 因为我们希望环越小越好(这样形成的环可以最多),立刻break。如果cur不等于0, 进入构造下一步q中所保存的值。q.appendleft((cur+net[i], path+[i]. i+1))
当cur==0跳出之后,我们需要对res进行update(self.res += len(path)-1)。同时我们把已经成环的i要从net中删掉。net = [net[i] for i in range(len(net)) if i not in path] 然后把这个net返回到主函数
4 在主函数中当net为空list的时候,意味着我们已经遍历过所有net的值,这时候得到的self.res就是最终答案。
class Solution:
    def minTransfers(self, transactions: List[List[int]]) -> int:
        if not transactions or len(transactions) == 0:
            return 0
        
        d = collections.defaultdict(int)
        for x, y, money in transactions:
            d[x] += money 
            d[y] -= money 
            
        net = [d[k] for k in d if d[k] != 0]
      #  print(net)
        self.res = 0 
        
        while net:
            q = collections.deque()
            q.append((net[0], [0], 1))
            net = self.bfs(net, q)
         #   print(net)
        return self.res 
    
    
    def bfs(self, net, q):
        while q:
            cur, path, start = q.pop()
            if not cur:
                break 
            for i in range(start, len(net)):
                q.appendleft((cur + net[i], path+[i], i+1))
        self.res += len(path)-1 
        path =set(path)
        net = [net[i] for i in range(len(net)) if i not in path]
        return net 

猜你喜欢

转载自www.cnblogs.com/sky37/p/12239967.html
今日推荐