Q:在本問題中, 樹指的是一個連通且無環的無向圖。
輸入一個圖,該圖由一個有着N個節點 (節點值不重復1, 2, ..., N) 的樹及一條附加的邊構成。附加的邊的兩個頂點包含在1到N中間,這條附加的邊不屬於樹中已存在的邊。
結果圖是一個以邊組成的二維數組。每一個邊的元素是一對[u, v] ,滿足 u < v,表示連接頂點u 和v的無向圖的邊。
返回一條可以刪去的邊,使得結果圖是一個有着N個節點的樹。如果有多個答案,則返回二維數組中最后出現的邊。答案邊 [u, v] 應滿足相同的格式 u < v。
示例 1:
輸入: [[1,2], [1,3], [2,3]]
輸出: [2,3]
解釋: 給定的無向圖為:
1
/ \
2 - 3
示例 2:
輸入: [[1,2], [2,3], [3,4], [1,4], [1,5]]
輸出: [1,4]
解釋: 給定的無向圖為:
5 - 1 - 2
| |
4 - 3
注意:
輸入的二維數組大小在 3 到 1000。
二維數組中的整數在1到N之間,其中N是輸入數組的大小。
A:
典型的並查集問題
並查集類:
1 public class Union { 2 int count;//樹的個數 3 int[] root;//每個點的根節點 4 int[] size;//一棵樹的節點數 5 6 Union(int m) { 7 root = new int[m]; 8 size = new int[m]; 9 for (int i = 0; i < m; i++) { 10 root[i] = i;//初始點,每個點的根節點都是自己 11 size[i] = 1;//每棵樹只有1個節點 12 } 13 count = m;//總共有m棵樹 14 } 15 16 public void unionF(int i, int j) { 17 int x = find(i);//i的根節點 18 int y = find(j);//j的根節點 19 if (x != y) { 20 if (size[x] > size[y]) {//x樹更大,把y接上去 21 root[y] = x; 22 size[y] += size[x]; 23 } else {//y樹更大,把x接上去 24 root[x] = y; 25 size[x] += size[y]; 26 } 27 count--; 28 } 29 } 30 31 public int find(int j) { 32 while (root[j] != j) { 33 //這句是為了壓縮路徑,不要的話可以跑的通,但效率變低 34 root[j] = root[root[j]]; 35 j = root[j]; 36 } 37 return j; 38 } 39 40 public int count() { 41 return count; 42 } 43 44 public boolean connected(int i, int j) { 45 int x = find(i); 46 int y = find(j); 47 return x == y; 48 } 49 }
代碼:如果兩個點曾經已經連接過了,再次連接說明是冗余連接
1 public int[] findRedundantConnection(int[][] edges) { 2 int num = edges.length; 3 Union u = new Union(num); 4 for (int[] edge : edges) { 5 if (u.connected(edge[0] - 1, edge[1] - 1)) 6 return edge; 7 u.unionF(edge[0] - 1, edge[1] - 1); 8 } 9 return new int[]{}; 10 }
Q:
給定從 0 到 n-1 標號的 n 個結點,和一個無向邊列表(每條邊以結點對來表示),請編寫一個函數用來判斷這些邊是否能夠形成一個合法有效的樹結構。
示例 1:
輸入: n = 5, 邊列表 edges = [[0,1], [0,2], [0,3], [1,4]]
輸出: true
示例 2:
輸入: n = 5, 邊列表 edges = [[0,1], [1,2], [2,3], [1,3], [1,4]]
輸出: false
注意:你可以假定邊列表 edges 中不會出現重復的邊。由於所有的邊是無向邊,邊 [0,1] 和邊 [1,0] 是相同的,因此不會同時出現在邊列表 edges 中。
A:
首先,如果形成了一棵樹,那么邊數量一定是點數量-1.
如果兩個點曾經已經連接過了,再次連接說明是冗余連接,不為樹。
然后同樣用並查集解決:
1 public boolean validTree(int n, int[][] edges) { 2 if (edges.length != n - 1) 3 return false; 4 Union u = new Union(n); 5 for (int i = 0; i < edges.length; i++) { 6 if (u.connected(edges[i][0], edges[i][1])) 7 return false; 8 u.unionF(edges[i][0], edges[i][1]); 9 } 10 return true; 11 }