[leetCode]1584. 连接所有点的最小费用

题目

https://leetcode-cn.com/problems/min-cost-to-connect-all-points/

在这里插入图片描述

Kruscal算法

最小生成树:
图的生成树是他的一棵含有所有顶点的无环连通子图。一幅加权图的最小生成树(MST)
是它的一棵权值最小的生成树。

题目可以转换为求最小生成树的权值总和

Kruscal算法流程:

  • 将图 G = { V , E } G = \{V, E\} G={V,E} 中所有的边按照从小到达排序,等长的边任意排序
  • 初始化图 G ′ 为 { V , 、 ∅ } G'为 \{V, 、\varnothing\} G{V,}从前往后扫描排序后的边,如果边 e e e连接了两个不同的连通分量则将该边加入图 G ′ G' G中。
  • 最后得到的图 G ′ G' G就是图 G G G的最小生成树

使用并查集维护连通性,若当前边两端不连通即可选择这条边。

class Solution {
    public int minCostConnectPoints(int[][] points) {
        int n = points.length;// 顶点数量
        UnionFind uf = new UnionFind(n);
        List<Edge> edges = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                edges.add(new Edge(distance(points, i, j), i, j));
            }
        }
        Collections.sort(edges, (o1, o2) -> o1.len - o2.len);
        int res = 0, num = 1;
        for (Edge edge : edges) {
            int len = edge.len, x = edge.x, y = edge.y;
            if (!uf.isConnected(x, y)) {
                res += len;
                num++;
                uf.union(x, y);
                if (num == n) break;
            }
        }
        return res;
    }

    private int distance(int[][] points, int x, int y) {
        return Math.abs(points[x][0] - points[y][0]) + Math.abs(points[x][1] - points[y][1]);
    }

    class UnionFind {
        private int[] parent;
        private int[] rank;
        public UnionFind(int n) {
            parent = new int[n];
            rank = new int[n];
            for (int i = 0; i < n; i++) {
                parent[i] = i;
                rank[i] = 1;
            }
        }
        public int find(int x) {
            if (x != parent[x]) {
                parent[x] = find(parent[x]);
            }
            return parent[x];
        }
        public void union(int x, int y) {
            int rootX = find(x);
            int rootY = find(y);
            if (rootX == rootY)
                return;
            if (rank[rootX] == rank[rootY]) {
                parent[rootX] = rootY;
                rank[rootY] += 1; 
            } else if (rank[rootX] < rank[rootY]) {
                parent[rootX] = rootY;
            } else {
                parent[rootY] = rootX;
            }
        }

        public boolean isConnected(int x, int y) {
            return find(x) == find(y);
        }
    }

    class Edge {
        int len, x, y;
        public Edge(int len, int x, int y) {
            this.len = len;
            this.x = x;
            this.y = y;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值