最小生成樹演算法(Prim, Kruskal)
阿新 • • 發佈:2021-01-20
連線所有點的最小費用
class Solution { public int minCostConnectPoints(int[][] points) { //prim演算法,時間複雜度 n^2 int res = 0, n = points.length; int[][] g = new int[n][n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { g[i][j] = Math.abs(points[i][0] - points[j][0]) + Math.abs(points[i][1] - points[j][1]); } }//點的集合,已經放入集合為true boolean[] v = new boolean[n]; //lowest[i] 表示 點i 到已放入集合的點的最短距離 int[] lowest = new int[n]; //先放入 點0 v[0] = true; //未放入點 i 到已放入點的集合的最短距離,這裡是[0],[1, n-1] for (int i = 1; i < n; i++) { lowest[i] = g[0][i]; } //還有n - 1個點沒有放入集合for (int i = 1; i < n; i++) { int min = Integer.MAX_VALUE, index = -1; for (int j = 0; j < n; j++) { if (v[j]) continue; if (min > lowest[j]) { index = j; min = lowest[j]; } } res+= min; v[index] = true; //更新lowest for (int j = 0; j < n; j++) { if (v[j]) continue; lowest[j] = Math.min(lowest[j], g[index][j]); } } return res; } }
class Solution { public int minCostConnectPoints(int[][] points) { //Kruskal演算法 int n = points.length, res = 0; //優先佇列(小到大) PriorityQueue<Edge> heap = new PriorityQueue<>((o1, o2) -> o1.dis - o2.dis); //並查集找環 UF uf = new UF(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]); heap.offer(new Edge(i, j, dis)); } } int mark = 0; while (!heap.isEmpty()) { Edge e = heap.poll(); if (uf.union(e.x, e.y)){ res += e.dis; mark++; } if (mark == n - 1) break; } return res; } class Edge { private int x, y, dis; public Edge(int x, int y, int dis) { this.x = x; this.y = y; this.dis = dis; } } //用並查集 class UF{ int[] parent; public UF(int n) { parent = new int[n]; for (int i = 0; i < n; i++) { parent[i] = i; } } private int find(int x) { if (x != parent[x]) { parent[x] = find(parent[x]); } return parent[x]; } public boolean union(int a, int b) { int rootA = find(a); int rootB = find(b); //如果a, b在連通,那麼加入a, b就會有環 if (rootA == rootB) return false; parent[rootA] = rootB; return true; } } }