Woodyiiiiiii / LeetCode

My private record of Leetcode solution

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Leetcode 1584. Min Cost to Connect All Points

Woodyiiiiiii opened this issue · comments

这是一道典型的图基本算法题,包含Prim(用堆优化)和Kruskal(并查集)算法,代码如下:
// Prim
class Solution {
    
    public int minCostConnectPoints(int[][] points) {
        return prim(points, 0);
    }

    public int prim(int[][] points, int start) {

        int res = 0;
        int n = points.length;
        int[][] matrix = new int[n][n];
        // 邻接矩阵,方便查询
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                matrix[i][j] = calculate(points, i, j);
                matrix[j][i] = matrix[i][j];
            }
        }

        // 访问数组
        int[] visited = new int[n];
        // 最小距离数组
        int[] dis = new int[n];

        // 将起始点加入访问数组并更新距离
        visited[start] = 1;
        dis[start] = -1;
        for (int i = 0; i < n; i++) {
            if (i != start) {
                dis[i] = matrix[start][i];
            }
        }

        // 遍历n - 1次
        for (int i = 0; i < n - 1; i++) {
            // 找到离最近的一个点的最小距离
            int min = Integer.MAX_VALUE;
            int index = -1;
            for (int j = 0; j < n; j++) {
                if (visited[j] == 0 && dis[j] < min) {
                    min = dis[j];
                    index = j;
                }
            }

            // 更新
            visited[index] = 1;
            for (int j = 0; j < n; j++) {
                if (visited[j] == 0 && matrix[index][j] < dis[j]) {
                    dis[j] = matrix[index][j];
                }
            }

            // amass
            res += min;
        }

        return res;
    }

    public int calculate(int[][] points, int i, int j) {
        return Math.abs(points[i][0] - points[j][0]) + Math.abs(points[i][1] - points[j][1]);
    }

}
Kruskal + Union find:
// Kruskal + Uninon find
class Solution {
    
    public int minCostConnectPoints(int[][] points) {
        
        int n = points.length;
        UnionSet union = new UnionSet(n);
        List<Edge> edges = new ArrayList<>();
        for (int i = 0; i < n; ++i) {
            for (int j = i + 1; j < n; ++j) {
                Edge edge = new Edge(i, j, calculate(points, i, j));
                edges.add(edge);
            }
        }
        
        // 排序
        Collections.sort(edges, new Comparator<Edge>() {
            public int compare(Edge edge1, Edge edge2) {
                return edge1.p - edge2.p;
            }
        });
        
        int ans = 0, cnt = 1;
        for (Edge edge : edges) {
            int x = edge.x, y = edge.y, p = edge.p;
            if (!union.merge(x, y)) {
                ans += p;
                cnt++;
                if (cnt == n) {
                    break;
                }
            }
        }
        
        return ans;
    }
    
    public int calculate(int[][] points, int i, int j) {
        return Math.abs(points[i][0] - points[j][0]) + Math.abs(points[i][1] - points[j][1]);
    }

}

class UnionSet {
    
    private int n;
    
    private int[] f;
    
    private int[] rank;
    
    public UnionSet(int n) {
        this.n = n;
        // 设置并查集,一开始每个节点的父节点是本身
        f = new int[n];
        for (int i = 0; i < n; ++i) {
            f[i] = i;
        }
        // 设置权重
        rank = new int[n];
        Arrays.fill(rank, 1);
    }
    
    // 查询根节点
    public int find(int x) {
        return f[x] == x ? x : (f[x] = find(f[x]));
    }
    
    // 先判断是否在同一集合,不是则集合合并
    public boolean merge(int x, int y) {
        
        int fx = find(x), fy = find(y);
        if (fx == fy) {
            return true;
        }
    
        // 找到权重最大的一个
        if (rank[fx] < rank[fy]) {
            int tmp = fx;
            fx = fy;
            fy = tmp;
        }
        
        rank[fx] += rank[fy];
        f[fy] = fx;
        
        return false;
        
    }
    
}

class Edge {
    
    // 点索引
    public int x;
    
    // 另一个点索引
    public int y;
    
    // 权
    public int p;
    
    public Edge(int x, int y, int p) {
        this.x = x;
        this.y = y;
        this.p = p;
    }
    
}