已解答
中等
相关标签
相关企业
提示
给你一个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;
}
}
}