LeetCode 85. 冗余連接 II
阿新 • • 發佈:2019-03-18
arrays span boolean 引導 這就是 als rect 屬於 指向
題目:
在本問題中,有根樹指滿足以下條件的有向圖。該樹只有一個根節點,所有其他節點都是該根節點的後繼。每一個節點只有一個父節點,除了根節點沒有父節點。
輸入一個有向圖,該圖由一個有著N個節點 (節點值不重復1, 2, ..., N) 的樹及一條附加的邊構成。附加的邊的兩個頂點包含在1到N中間,這條附加的邊不屬於樹中已存在的邊。
結果圖是一個以邊
組成的二維數組。 每一個邊
的元素是一對 [u, v]
,用以表示有向圖中連接頂點 u
and v
和頂點的邊,其中父節點u
是子節點v
的一個父節點。
返回一條能刪除的邊,使得剩下的圖是有N個節點的有根樹。若有多個答案,返回最後出現在給定二維數組的答案。
示例:
輸入: [[1,2], [1,3], [2,3]] 輸出: [2,3] 解釋: 給定的有向圖如下: 1 / v v 2-->3
輸入: [[1,2], [2,3], [3,4], [4,1], [1,5]] 輸出: [4,1] 解釋: 給定的有向圖如下: 5 <- 1 -> 2 ^ | | v 4 <- 3
題解:
在以上題目中有一句比較關鍵的句子 : 該圖由一個有著N個節點 (節點值不重復1, 2, ..., N) 的樹及一條附加的邊構成。附加的邊
的兩個頂點包含在1到N中間,這條附加的邊不屬於樹中已存在的邊。
這句話其實是引導我們思路的,我們可以知道題目所說的有根樹具有三個性質。第一,有根樹存在入度為0的節點(根節點),第二有根樹除了
根節點其他節點的入度都為1。第三有根樹所有節點都是連通的。
如若一顆有根樹加上一條邊的話,那麽加上的邊存在以下三種情況:
1)邊的兩端是同一節點
判定方式 : 直接看兩遍是否相等
處理 : 直接可以知道這條邊肯定不是原有的,返回當前邊
2)兩端不是同一節點,並且被指向的是根節點。
判定方式 : 如若被指向的那端統計之後出現了所有節點或者不存在入度為2的節點
處理 : 因為根被指向了後一定會形成環,故而處理的可能性很多(除去環內任意邊),但是需要註意是否存在示例2中的情況,如若除去邊[1,5],就會導致該有根樹不連通,並且依然有環。 因為是否連通使用並查集很容易檢測是否連通
,故而這裏我選擇了直接使用並查集。
3)兩端不是同一節點,並且被指向的是非根節點。
判定方式 : 剩下的情況都是3)//存在入度為2的節點
處理 : 因為存在入度為2的節點,所以在這就是在兩條指向入度為2節點內直接二選一,但是這裏不能隨便選,必須保證如若因為這條邊成環(例如示例一加上一個節點4並且4指向2),也就是 : [[4, 2],[1,2], [1,3], [2,3]]
,這時指向2的一共有兩個節點 4 和 1,這時候如若選擇刪除[1,2]則會導致整張圖不連通,故而需要檢查連通性來選擇刪除兩個節點的哪個,依然使用並查集。
代碼:
1 int n; 2 public int[] findRedundantDirectedConnection(int[][] edges) { 3 this.n = edges.length; 4 int[] table = new int[n]; 5 Arrays.fill(table, -1); 6 int other = -1; 7 for (int i = 0; i < n; i++) { 8 if (edges[i][0] == edges[i][1]) { 9 return edges[i]; 10 } 11 int index = edges[i][1] - 1; 12 if (table[index] != -1) { 13 other = i; 14 } else { 15 table[index] = i; 16 } 17 } 18 // 如若指向非根 19 if (other != -1) { 20 // 且 如若刪除了後面那個節點 仍然是 連通的。 21 if (this.isConnected(edges, other)) 22 return edges[other]; 23 else 24 return edges[table[edges[other][1] - 1]]; 25 } 26 for (int i = n - 1; i >= 0; i--) { 27 //如若除去i還是連通的 28 if (this.isConnected(edges, i)) { 29 return edges[i]; 30 } 31 } 32 return new int[] {}; 33 } 34 35 /** 36 * 若除去第i條邊 37 * 38 * @param edges 39 * @param i 40 * @return 41 */ 42 int[] table; 43 44 public boolean isConnected(int[][] edges, int i) { 45 this.table = new int[n]; 46 for (int j = 0; j < n; j++) { 47 table[j] = j; 48 } 49 for (int j = 0; j < n; j++) { 50 if (j != i) 51 union(edges[j][0] - 1, edges[j][1] - 1); 52 } 53 boolean flag = true; 54 for (int k = 0; k < n; k++) { 55 if (table[k] == k) { 56 if (flag) { 57 flag = false; 58 } else { 59 return false; 60 } 61 } 62 } 63 return true; 64 } 65 66 public boolean union(int i, int j) { 67 int iIndex = this.find(i); 68 int jIndex = this.find(j); 69 if (iIndex == jIndex) { 70 return false; 71 } 72 table[iIndex] = jIndex; 73 return true; 74 } 75 76 public int find(int i) { 77 while (table[i] != i) { 78 i = table[i]; 79 } 80 return i; 81 }
LeetCode 85. 冗余連接 II