★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公衆號:山青詠芝(shanqingyongzhi)
➤博客園地址:山青詠芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址: http://www.javashuo.com/article/p-zjrfktzn-me.html
➤若是連接不是山青詠芝的博客園地址,則多是爬取做者的文章。
➤原文已修改更新!強烈建議點擊原文地址閱讀!支持做者!支持原創!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★html
In this problem, a rooted tree is a directed graph such that, there is exactly one node (the root) for which all other nodes are descendants of this node, plus every node has exactly one parent, except for the root node which has no parents.node
The given input is a directed graph that started as a rooted tree with N nodes (with distinct values 1, 2, ..., N), with one additional directed edge added. The added edge has two different vertices chosen from 1 to N, and was not an edge that already existed.git
The resulting graph is given as a 2D-array of edges
. Each element of edges
is a pair [u, v]
that represents a directed edge connecting nodes u
and v
, where u
is a parent of child v
.github
Return an edge that can be removed so that the resulting graph is a rooted tree of N nodes. If there are multiple answers, return the answer that occurs last in the given 2D-array.數組
Example 1:微信
Input: [[1,2], [1,3], [2,3]] Output: [2,3] Explanation: The given directed graph will be like this: 1 / \ v v 2-->3
Example 2:app
Input: [[1,2], [2,3], [3,4], [4,1], [1,5]] Output: [4,1] Explanation: The given directed graph will be like this: 5 <- 1 -> 2 ^ | | v 4 <- 3
Note:this
在本問題中,有根樹指知足如下條件的有向圖。該樹只有一個根節點,全部其餘節點都是該根節點的後繼。每個節點只有一個父節點,除了根節點沒有父節點。spa
輸入一個有向圖,該圖由一個有着N個節點 (節點值不重複1, 2, ..., N) 的樹及一條附加的邊構成。附加的邊的兩個頂點包含在1到N中間,這條附加的邊不屬於樹中已存在的邊。code
結果圖是一個以邊
組成的二維數組。 每個邊
的元素是一對 [u, v]
,用以表示有向圖中鏈接頂點 u
and v
和頂點的邊,其中父節點u
是子節點v
的一個父節點。
返回一條能刪除的邊,使得剩下的圖是有N個節點的有根樹。如有多個答案,返回最後出如今給定二維數組的答案。
示例 1:
輸入: [[1,2], [1,3], [2,3]] 輸出: [2,3] 解釋: 給定的有向圖以下: 1 / \ v v 2-->3
示例 2:
輸入: [[1,2], [2,3], [3,4], [4,1], [1,5]] 輸出: [4,1] 解釋: 給定的有向圖以下: 5 <- 1 -> 2 ^ | | v 4 <- 3
注意:
36ms
1 class Solution { 2 func findRedundantDirectedConnection(_ edges: [[Int]]) -> [Int] { 3 guard edges.isEmpty == false else { 4 return [] 5 } 6 var parents: [Int] = [] 7 8 var res1: [Int] = [] 9 var res2: [Int] = [] 10 11 for i in 0...edges.count { 12 parents.append(i) 13 } 14 for edge in edges { 15 let x = edge[0] 16 let y = edge[1] 17 let rootX = find(&parents, x) 18 let rootY = find(&parents, y) 19 if rootX != rootY { 20 if rootY != y { 21 res1 = edge 22 } else { 23 parents[y] = x 24 } 25 } else { 26 res2 = edge 27 } 28 } 29 if res1.isEmpty == true { 30 return res2 31 } 32 if res2.isEmpty == true { 33 return res1 34 } 35 36 for edge in edges { 37 if edge[1] == res1[1] { 38 return edge 39 } 40 } 41 return [] 42 } 43 44 private func find(_ parents: inout [Int], _ val: Int) -> Int { 45 if parents[val] != val { 46 parents[val] = find(&parents, parents[val]) 47 } 48 return parents[val] 49 } 50 }
40ms
1 class Solution { 2 func findRedundantDirectedConnection(_ edges: [[Int]]) -> [Int] { 3 guard edges.isEmpty == false else { 4 return [] 5 } 6 var parents: [Int] = [] 7 8 var res1: [Int] = [] 9 var res2: [Int] = [] 10 11 for i in 0...edges.count { 12 parents.append(i) 13 } 14 for edge in edges { 15 let x = edge[0] 16 let y = edge[1] 17 let rootX = find(parents, x) 18 let rootY = find(parents, y) 19 if rootX != rootY { 20 if rootY != y { 21 res1 = edge 22 } else { 23 parents[y] = x 24 } 25 } else { 26 res2 = edge 27 } 28 } 29 if res1.isEmpty == true { 30 return res2 31 } 32 if res2.isEmpty == true { 33 return res1 34 } 35 36 for edge in edges { 37 if edge[1] == res1[1] { 38 return edge 39 } 40 } 41 return [] 42 } 43 44 private func find(_ parents: [Int], _ val: Int) -> Int { 45 if val == parents[val] { 46 return val 47 } 48 return find(parents, parents[val]) 49 } 50 }
1 class Solution { 2 func findRedundantDirectedConnection(_ edges: [[Int]]) -> [Int] { 3 var edges = edges 4 var n:Int = edges.count 5 var root:[Int] = [Int](repeating:0,count:n + 1) 6 var first:[Int] = [Int]() 7 var second:[Int] = [Int]() 8 for i in 0..<edges.count 9 { 10 if root[edges[i][1]] == 0 11 { 12 root[edges[i][1]] = edges[i][0] 13 } 14 else 15 { 16 first = [root[edges[i][1]], edges[i][1]] 17 second = edges[i] 18 edges[i][1] = 0 19 } 20 } 21 for i in 0...n 22 { 23 root[i] = i 24 } 25 for edge in edges 26 { 27 if edge[1] == 0 {continue} 28 var x:Int = getRoot(&root, edge[0]) 29 var y:Int = getRoot(&root, edge[1]) 30 if x == y 31 { 32 return first.isEmpty ? edge : first 33 } 34 root[x] = y 35 } 36 return second 37 } 38 39 func getRoot(_ root:inout [Int],_ i:Int) -> Int 40 { 41 return i == root[i] ? i : getRoot(&root, root[i]) 42 } 43 }
52ms
1 class Solution { 2 var parents = [Int: Int]() 3 var candidate1 = [-1, -1] 4 var candidate2 = [-1, -1] 5 6 func findRedundantDirectedConnection(_ edges: [[Int]]) -> [Int] { 7 var edges = edges 8 // ****** Step 1: Check if there is a 2-parent situation. ****** 9 for i in 0..<edges.count { 10 let parent = edges[i][0] 11 let child = edges[i][1] 12 if let existedParent = parents[child] { 13 // If there is already an existed parent for the current child, this means we have found a 2-parent situation. 14 // Set candidate1 to the previously-found edge. 15 candidate1 = [existedParent, child] 16 // Set candidate2 to the current edge. 17 candidate2 = edges[i] 18 // Invalidate the curent edge. 19 edges[i][1] = -1 20 } else { 21 // If there is no 2-parent situation, we record the parent for each child. 22 parents[child] = parent 23 } 24 } 25 26 // ****** Step2: Perform union-find to find if there is any cycles. ****** 27 // Reset parent dictionary. 28 parents = [Int: Int]() 29 // Perform union-find. 30 var foundEdge: [Int]? 31 for edge in edges { 32 guard edge[1] != -1 else { 33 continue 34 } 35 if let foundEdge = union(edge[0], edge[1]) { 36 return foundEdge 37 } 38 } 39 // If we reach this point, that means we previously invalidated the corrent "wrong" edge and there is no cycle, 40 // which is situation #1, just return candidate2. 41 return candidate2 42 } 43 44 private func union(_ x: Int, _ y: Int) -> [Int]? { 45 let xParnet = find(x) 46 let yParent = find(y) 47 guard xParnet != yParent else { 48 // If we have found a cycle... 49 if candidate1[0] == -1 { 50 // If there is no 2-parent situation at all, which is situation #2, return the current edge. 51 return [x, y] 52 } else { 53 // If there is a 2-parent situation, which is situation #3, return candidate 1. 54 return candidate1 55 } 56 } 57 // If no cycle is found, we are good and return nothing. 58 parents[yParent] = xParnet 59 return nil 60 } 61 62 private func find(_ x: Int) -> Int { 63 // Recursively find the parent or return the node itself if this node has no parent. 64 if parents[x] == nil { 65 return x 66 } 67 return find(parents[x]!) 68 } 69 }
56ms
1 class Solution { 2 func findRedundantDirectedConnection(_ edges: [[Int]]) -> [Int] { 3 var adjacentInfo: [Int: Set<Int>] = [:] 4 var parentInfo: [Int: [Int]] = [:] 5 var target: Int = -1 6 for edge in edges { 7 var adjacentSet: Set<Int> 8 if let adjSet = adjacentInfo[edge[0]] { 9 adjacentSet = adjSet 10 } else { 11 adjacentSet = Set() 12 } 13 adjacentSet.insert(edge[1]) 14 adjacentInfo[edge[0]] = adjacentSet 15 16 if var parents = parentInfo[edge[1]] { 17 target = edge[1] 18 parents.append(edge[0]) 19 parentInfo[edge[1]] = parents 20 } else{ 21 parentInfo[edge[1]] = [edge[0]] 22 } 23 } 24 25 if target != -1, let parents = parentInfo[target] { 26 var root: Int = parents.first! 27 for key in adjacentInfo.keys { 28 if parentInfo[key] == nil { 29 root = key 30 break 31 } 32 } 33 34 let candidate = parents.last! 35 36 var removed = adjacentInfo[candidate] 37 removed?.remove(target) 38 adjacentInfo[candidate] = removed ?? [] 39 if hasPath(from: root, to: target, info: adjacentInfo) { 40 return [candidate, target] 41 } else { 42 return [parents.first!, target] 43 } 44 } 45 46 for edge in edges.reversed() { 47 if hasPath(from: edge[1], to: edge[0], info: adjacentInfo) { 48 return edge 49 } 50 } 51 return [] 52 } 53 func hasPath(from: Int, to: Int, info: [Int: Set<Int>]) -> Bool { 54 var visited: Set<Int> = Set() 55 var queue: [Int] = [from] 56 while queue.count > 0 { 57 let current = queue.first! 58 queue.remove(at: 0) 59 visited.insert(current) 60 61 if current == to { 62 return true 63 } 64 guard let adjs = info[current] else { continue } 65 for neighbor in adjs { 66 if visited.contains(neighbor) == false { 67 queue.append(neighbor) 68 } 69 } 70 } 71 return false 72 } 73 }