You are given an array points
representing integer coordinates of some points on a 2D-plane, where points[i] = [xi, yi]
.
The cost of connecting two points [xi, yi]
and [xj, yj]
is the manhattan distance between them: |xi - xj| + |yi - yj|
, where |val|
denotes the absolute value of val
.
Return the minimum cost to make all points connected. All points are connected if there is exactly one simple path between any two points.
Example 1:
Input: points = [[0,0],[2,2],[3,10],[5,2],[7,0]] Output: 20 Explanation: We can connect the points as shown above to get the minimum cost of 20. Notice that there is a unique path between every pair of points.
Example 2:
Input: points = [[3,12],[-2,5],[-4,1]] Output: 18
思路:这题跟 1135 Connecting Cities With Minimum Cost 一模一样,就是抽象化的minimum spanning tree, 每次用最小的边去connect graph;Union Find 直觉解决问题;
class Solution {
private class Connection {
public int from;
public int to;
public int cost;
public Connection(int from, int to, int cost) {
this.from = from;
this.to = to;
this.cost = cost;
}
}
private class UnionFind {
private int[] father;
private int size;
public UnionFind(int n) {
this.father = new int[n + 1];
for(int i = 0; i <= n; i++) {
father[i] = i;
}
this.size = n;
}
public int find(int x) {
int j = x;
while(father[j] != j) {
j = father[j];
}
// path compression;
while(x != j) {
int fx = father[x];
father[x] = j;
x = fx;
}
return j;
}
public void union(int a, int b) {
int root_a = find(a);
int root_b = find(b);
if(root_a != root_b) {
father[root_a] = root_b;
size--;
}
}
public int getSize() {
return this.size;
}
}
public int minCostConnectPoints(int[][] points) {
List clist = new ArrayList();
int n = points.length;
for(int i = 0; i < n; i++) {
for(int j = i + 1; j < n; j++) {
clist.add(new Connection(i, j,
getCost(points[i][0], points[i][1], points[j][0], points[j][1])));
}
}
Collections.sort(clist, (a, b) -> (a.cost - b.cost));
UnionFind uf = new UnionFind(n);
int totalcost = 0;
for(Connection connection: clist) {
int a = connection.from;
int b = connection.to;
int cost = connection.cost;
if(uf.find(a) != uf.find(b)) {
uf.union(a, b);
totalcost += cost;
}
}
return totalcost;
}
private int getCost(int x1, int y1, int x2, int y2) {
return Math.abs(x1 - x2) + Math.abs(y1 - y2);
}
}
思路2: 这题也可以用dijkstra来做,一个node,可以connect到别的node,可以有N条边,那么就是HashMap
class Solution {
private class Node {
public int index;
public int cost;
public Node(int index, int cost) {
this.index = index;
this.cost = cost;
}
}
public int minCostConnectPoints(int[][] points) {
HashMap> graph = new HashMap<>();
int n = points.length;
for(int i = 0; i < n; i++) {
for(int j = i + 1; j < n; j++) {
int from = i;
int to = j;
int cost = getCost(points[i][0], points[i][1], points[j][0], points[j][1]);
graph.putIfAbsent(from, new ArrayList());
graph.putIfAbsent(to, new ArrayList());
graph.get(from).add(new Node(to, cost));
graph.get(to).add(new Node(from, cost));
}
}
PriorityQueue pq = new PriorityQueue((a, b) -> (a.cost - b.cost));
pq.offer(new Node(0, 0));
HashSet visited = new HashSet();
int totalcost = 0;
while(!pq.isEmpty()) {
Node node = pq.poll();
if(visited.contains(node.index)) {
continue;
}
visited.add(node.index);
totalcost += node.cost;
if(graph.get(node.index) != null) {
for(Node neighbor: graph.get(node.index)) {
if(!visited.contains(neighbor.index)) {
pq.offer(neighbor);
}
}
}
}
return totalcost;
}
private int getCost(int x1, int y1, int x2, int y2) {
return Math.abs(x1 - x2) + Math.abs(y1 - y2);
}
}