【最小生成树】day79_1584. 连接所有点的最小费用

62 阅读2分钟

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

已解答

中等

相关标签

相关企业

提示

给你一个points 数组,表示 2D 平面上的一些点,其中 points[i] = [xi, yi] 。

连接点 [xi, yi] 和点 [xj, yj] 的费用为它们之间的 曼哈顿距离 :|xi - xj| + |yi - yj| ,其中 |val| 表示 val 的绝对值。

请你返回将所有点连接的最小总费用。只有任意两点之间 有且仅有 一条简单路径时,才认为所有点都已连接。

 

示例 1:

输入: points = [[0,0],[2,2],[3,10],[5,2],[7,0]]
输出: 20
解释: 
我们可以按照上图所示连接所有点得到最小总费用,总费用为 20 。
注意到任意两个点之间只有唯一一条路径互相到达。

示例 2:

输入: points = [[3,12],[-2,5],[-4,1]]
输出: 18

示例 3:

输入: points = [[0,0],[1,1],[1,0],[-1,1]]
输出: 4

示例 4:

输入: points = [[-1000000,-1000000],[1000000,1000000]]
输出: 4000000

示例 5:

输入: points = [[0,0]]
输出: 0

 

提示:

  • 1 <= points.length <= 1000
  • -106 <= xi, yi <= 106
  • 所有点 (xi, yi) 两两不同。

题解:

思路:并查集

时间复杂度:O(n^2)

空间复杂度:O(n)

class Solution {
    
    // 并查集集合
    List<Integer> p;

    public int minCostConnectPoints(int[][] points) {
        p = new ArrayList<>();
        int n = points.length;
        // 初始化并查集
        for(int i = 0; i < n; i++) {
            p.add(i);
        }
        // 添加所有可能的边到列表中
        List<Edge> edges = new ArrayList<>();
        for(int i = 0; i < n - 1; i++) {
            for(int j = i + 1; j < n; j++) {
                // 添加第i个点和第j个点组成的边
                edges.add(new Edge(i, j, Math.abs(points[i][0] - points[j][0]) + Math.abs(points[i][1] - points[j][1])));
            }
        }
        // 进行一个升序排序,为了优先选取短的边
        Collections.sort(edges, (a, b) -> a.val - b.val);

        // 从低到高遍历所有边
        int res = 0;
        for(Edge e : edges) {
            // 查找这条边两个端点所处的集合根元素
            int a = find(e.a), b = find(e.b);
            // 如果这两条边不是一个集合的,那么就添加这条边
            if(a != b) {
                // 并且将这两个点所在的集合根元素加入一个集合
                p.set(a, b);
                // 答案中添加这条边长度
                res += e.val;
            }
        }

        return res;
    }

    // 并查集模板方法,用于查找根元素
    public int find(int x) {
        if(p.get(x) != x) {
            p.set(x, find(p.get(x)));
        }

        return p.get(x);
    }

    // 定义边
    public class Edge {
        // 分别表示一条边两个点的索引和边长
        int a, b, val;
        public Edge(int a, int b, int val) {
            this.a = a;
            this.b = b;
            this.val = val;
        }
    }
}