分析
最小生成树的问题
kruskal : 每次加入最短的边,且边加入后不会构成环。
并查集:判断加入的边的两点是否会构成回环
edge数据结构:将边,两个端点整合起来
解法一:kruskal+并查集
class Solution {
public int minCostConnectPoints(int[][] points) {
int n = points.length;
List<edge> list = new ArrayList<>();
Parent parent = new Parent(n);
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
int dis = Math.abs(points[i][0] - points[j][0]) + Math.abs(points[i][1] - points[j][1]);
list.add(new edge(i,j,dis));
}
}
Collections.sort(list,(a,b)->(a.distance-b.distance));
int ans = 0;
for (edge e : list) {
if (!parent.isConnect(e.start,e.end)) {
parent.union(e.start,e.end);
ans += e.distance;
}
}
return ans;
}
class edge{
int start;
int end;
int distance;
edge(int a, int b, int c) {
start = a;
end = b;
distance = c;
}
}
class Parent {
int[] parent;
Parent (int n) {
parent = new int[n];
for (int i = 0; i < n; i++) {
parent[i] = i;
}
}
public int find(int x) {
if (x != parent[x]) {
x = find(parent[x]);
}
return parent[x];
}
public void union(int i, int j){
int a = find(i);
int b = find(j);
parent[a] = b;
}
public boolean isConnect(int i, int j) {
int a = find(i);
int b = find(j);
return a == b;
}
}
}
20240307第二次做
class Solution {
public int minCostConnectPoints(int[][] points) {
int n = points.length;
int[][] dis = new int[n*(n-1)/2][3];
int index = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
int distance = Math.abs(points[i][0]-points[j][0]) + Math.abs(points[i][1]-points[j][1]);
dis[index][0] = i;
dis[index][1] = j;
dis[index++][2] = distance;
}
}
Arrays.sort(dis, new Comparator<int[]>(){
public int compare(int[] a, int[] b) {
// return a[2] > b[2] ? 1 : -1;
if (a[2] == b[2]) {
return 0;
}
return a[2] > b[2] ? 1 : -1;
}
});
int ans = 0, count = 0;
int[] parent = new int[n];
for (int i = 0; i < n; i++) {
parent[i] = i;
}
for (int[] di : dis) {
if (find(parent, di[0]) != find(parent, di[1])) {
count++;
ans += di[2];
parent[find(parent, di[0])] = find(parent, di[1]);
}
if (count == n - 1) {
break;
}
}
return ans;
}
public int find(int[] parent, int i) {
if (parent[i] != i) {
parent[i] = find(parent, parent[i]);
}
return parent[i];
}
}
prim算法
class Solution {
public int minCostConnectPoints(int[][] points) {
int ans = 0;
int n = points.length;
int[][] adjoin = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == j) {
adjoin[i][j] = Integer.MAX_VALUE;
}
adjoin[i][j] = Math.abs(points[i][0]-points[j][0]) + Math.abs(points[i][1]-points[j][1]);
}
}
boolean[] visited = new boolean[n];
visited[0] = true;
int[] dis = new int[n];
for (int i = 0; i < n; i++) {
dis[i] = adjoin[0][i];
}
for (int i = 1; i < n; i++) {
int min = Integer.MAX_VALUE;
int next = 0;
for (int j = 0; j < n; j++) {
if (!visited[j] && dis[j] < min) {
min = dis[j];
next = j;
}
}
ans += min;
visited[next] = true;
for (int j = 0; j < n; j++) {
if (!visited[j] && adjoin[next][j] < dis[j]) {
dis[j] = adjoin[next][j];
}
}
}
return ans;
}
}