|
| 1 | +### 685. Redundant Connection II |
| 2 | + |
| 3 | +题目: |
| 4 | +<https://leetcode.com/problems/redundant-connection-ii/> |
| 5 | + |
| 6 | + |
| 7 | +难度 : Hard |
| 8 | + |
| 9 | + |
| 10 | + |
| 11 | +我们先定义一下,每条边的第一个点是parent,第二个点是child,例如 2 -> 1 中 node 2 就是 parent,而 node 1 就是 child |
| 12 | + |
| 13 | +明确这个之后,我们要知道图中有一条边是 invalid 的,去除它之后整个图就变成了一棵树,那么什么情况下一个边会导致树变成图呢: |
| 14 | + |
| 15 | +1. 如果一个child 在此之前已经有过一个parent了,那么意味着它有两个parent,这在树中肯定是不合法的。 |
| 16 | +在代码中体现为```node_parent[child] != child```,这说明在碰到此时的parent之前我们就已经更新过node_parent[child]了,即child之前已经有一个parent了 |
| 17 | +2. 如果一个child 的 parent 的 parent(或者一直往上找) 就是 child 本身,那么这意味着有环,这在树中也肯定是不合法的。 |
| 18 | +在代码中体现为```find(node_parents, parent) == child```, 这说明child的parent的parent或以上就是child本身,即有环。 |
| 19 | +例如 ```1 --> 2 --> 1```或者```1 --> 2 --> 3 --> 1``` |
| 20 | + |
| 21 | +因此我们可以定义一个列表 node_parent,在最开始的时候,此列表的 index 和 value 一一相等。 |
| 22 | + |
| 23 | +然后我们对edges进行第一轮遍历(正序遍历),并且用count来计数不合法的边: |
| 24 | +- 如果只找到一条不合法的边,那么直接返回它即可 |
| 25 | +- 如果有超过一条不合法的边,那么我们就进行第二轮遍历(逆序遍历),返回碰到的第一条不合法的边, |
| 26 | +这里是为了节约时间,因为如题意我们要返回的是最后一条出现的边,那么我们逆序就更省时间嘛 |
| 27 | + |
| 28 | + |
| 29 | +```python |
| 30 | +class Solution(object): |
| 31 | + def findRedundantDirectedConnection(self, edges): |
| 32 | + """ |
| 33 | + :type edges: List[List[int]] |
| 34 | + :rtype: List[int] |
| 35 | + """ |
| 36 | + |
| 37 | + def find(node_parent, parent): |
| 38 | + return parent if node_parent[parent] == parent else find(node_parent, node_parent[parent]) |
| 39 | + |
| 40 | + n, count = len(edges), 0 # 用 count 来计数不合法的边 |
| 41 | + node_parent = [i for i in range(n+1)] |
| 42 | + res = [0, 0] |
| 43 | + |
| 44 | + # 第一轮查找不合法的边 (正序) |
| 45 | + for i in range(n): |
| 46 | + parent, child = edges[i][0], edges[i][1] |
| 47 | + if node_parent[child] != child or find(node_parent, parent) == child: |
| 48 | + res = edges[i] |
| 49 | + count += 1 |
| 50 | + else: |
| 51 | + node_parent[child] = parent |
| 52 | + if count == 1: # 如果只有一条不合法的边,直接返回 |
| 53 | + return res |
| 54 | + |
| 55 | + # 重置 node_parent 并开始第二轮查找 (逆序) |
| 56 | + node_parent = [i for i in range(n+1)] |
| 57 | + for i in range(n-1, -1, -1): |
| 58 | + parent, child = edges[i][0], edges[i][1] |
| 59 | + if node_parent[child] != child or find(node_parent, parent) == child: |
| 60 | + return edges[i] |
| 61 | + else: |
| 62 | + node_parent[child] = parent |
| 63 | + return res |
| 64 | +``` |
| 65 | +这道题感谢[xyzxuyizhen](https://leetcode.com/problems/redundant-connection-ii/discuss/128596/Easy-to-understand-Java-Solution-Union-Find)大佬, |
| 66 | +看到他的思路才逃离了我之前的很复杂的想法。 |
0 commit comments