【Leetcode】465. Optimal Account Balancing

题目地址:

https://leetcode.com/problems/optimal-account-balancing/

给定一个有向图,每个图有个边权。定义一个点的“度”为其出边边权总和减去其入边边权总和。现在允许在图中加入若干条带权边,问要使得每个顶点的度都变成 0 0 0,至少需要加多少条边。

参考https://blog.csdn.net/qq_46105170/article/details/118718528。代码如下:

import java.util.*;

public class Solution {
    public int minTransfers(int[][] transactions) {
        int n = 0;
        Map<Integer, Integer> map = new HashMap<>();
        for (int[] tran : transactions) {
            map.putIfAbsent(tran[0], n++);
            map.putIfAbsent(tran[1], n++);
        }
        
        int[] out = new int[n];
        for (int[] trans : transactions) {
            int from = map.get(trans[0]), to = map.get(trans[1]), x = trans[2];
            out[from] += x;
            out[to] -= x;
        }
    
        List<Integer> list = new ArrayList<>();
        // 把度已经为0的点略过
        for (int x : out) {
            if (x != 0) {
                list.add(x);
            }
        }
    
        n = list.size();
        int[] f = new int[1 << n];
        Arrays.fill(f, 0x3f3f3f3f);
        f[0] = 0;
        for (int i = 1; i < 1 << n; i++) {
            int sum = 0, cnt = 0;
            for (int j = 0; j < n; j++) {
                if ((i >> j & 1) == 1) {
                    sum += list.get(j);
                    cnt++;
                }
            }
            
            if (sum == 0) {
                f[i] = cnt - 1;
                for (int j = 0; j < i; j++) {
                    if ((j & i) == j) {
                        f[i] = Math.min(f[i], f[j] + f[i - j]);
                    }
                }
            }
        }
        
        return f[(1 << n) - 1];
    }
}

时间复杂度 O ( 4 n ) O(4^n) O(4n)(实际不会这么慢,因为和为 0 0 0的子集数一般不会特别多,可以近似认为是 O ( n 2 n ) O(n2^n) O(n2n)复杂度),空间 O ( 2 n ) O(2^n) O(2n)

你可能感兴趣的:(LC,贪心,动态规划与记忆化搜索,算法,leetcode,java)