Skip to content

Commit 9eec7dd

Browse files
committed
684-redundant-connection.md Add Python Solution.
1 parent da9d724 commit 9eec7dd

5 files changed

Lines changed: 181 additions & 2 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,5 +72,6 @@ You can skip the more difficult problems and do them later.
7272
- [127. Word Ladder](solutions/1-1000/127-word-ladder.md) was solved in _Python_.
7373
- [1971. Find if Path Exists in Graph](solutions/1001-2000/1971-find-if-path-exists-in-graph.md) was solved in _Python, Java, C++, JavaScript, C#, Go, Ruby_ and 2 solutions.
7474
- [684. Redundant Connection](solutions/1-1000/684-redundant-connection.md) was solved in _Python, Java, C++, JavaScript, C#, Go, Ruby_.
75+
- [685. Redundant Connection II](solutions/1-1000/685-redundant-connection-ii.md) was solved in _Python_.
7576

7677
More LeetCode problems will be added soon...

images/examples/685_1.jpg

7.07 KB
Loading

images/examples/685_2.jpg

10.2 KB
Loading

solutions/1-1000/684-redundant-connection.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,12 @@ Output: [1,4]
4848
- `UnionFind` algorithm typically has three methods:
4949
- The `unite(node1, node2)` operation is used to merge two trees.
5050
- The `find_root(node)` method is used to return the root of a node.
51-
- The `same_root(node1, node2)` method is used to determine whether two nodes are in the same tree.
51+
- The `same_root(node1, node2) == true` method is used to determine whether two nodes are in the same tree.
5252

5353
## Approach (UnionFind algorithm)
5454
1. Initially, each node is in its own group.
5555
1. Iterate `edges` data and `unite(node1, node2)`.
56-
1. As soon as `same_root(node1, node2)`, return `[node1, node2]`.
56+
1. As soon as `same_root(node1, node2) == true` (a cycle will be formed), return `[node1, node2]`.
5757

5858
## Complexity
5959
* Time: `O(n)`.
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
# LeetCode 685. Redundant Connection II's Solution
2+
LeetCode problem link: [685. Redundant Connection II](https://leetcode.com/problems/redundant-connection-ii)
3+
4+
## LeetCode problem description
5+
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.
6+
7+
The given input is a directed graph that started as a rooted tree with `n` nodes (with distinct values from `1` to `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.
8+
9+
The resulting graph is given as a 2D-array of `edges`. Each element of `edges` is a pair `[ui, vi]` that represents a directed edge connecting nodes `ui` and `vi`, where `ui` is a parent of child `vi`.
10+
11+
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.
12+
13+
### Example 1
14+
![](../../images/examples/685_1.jpg)
15+
```
16+
Input: edges = [[1,2],[1,3],[2,3]]
17+
Output: [2,3]
18+
```
19+
20+
### Example 2
21+
![](../../images/examples/685_2.jpg)
22+
```
23+
Input: edges = [[1,2],[2,3],[3,4],[4,1],[1,5]]
24+
Output: [4,1]
25+
```
26+
27+
### Constraints
28+
- `n == edges.length`
29+
- `3 <= n <= 1000`
30+
- `edges[i].length == 2`
31+
- `1 <= ui, vi <= n`
32+
- `ui != vi`
33+
34+
## Intuition
35+
- Because a cycle is formed, the directed tree is no longer a directed tree. There are two cases to consider:
36+
1. If there is a vertex with in-degree 2, it will form a cycle. So one of the edges needs to be removed (returned).
37+
2. If there is no vertex with in-degree 2, once a cycle is formed, return the edge that causes the cycle.
38+
39+
- We are given `edges` data and need to divide them into multiple groups, each group can be abstracted into a **tree**.
40+
- Finally, those trees will be merged into one tree.
41+
- `UnionFind` algorithm is designed for grouping and searching data.
42+
43+
### 'UnionFind' algorithm
44+
- `UnionFind` algorithm typically has three methods:
45+
- The `unite(node1, node2)` operation is used to merge two trees.
46+
- The `find_root(node)` method is used to return the root of a node.
47+
- The `same_root(node1, node2)` method is used to determine whether two nodes are in the same tree.
48+
49+
## Approach
50+
1. Iterate `edges` data to look for the `two_conflict_edges` (two edges caused a vertex with in-degree 2).
51+
1. Initially, each node is in its own group.
52+
1. Iterate `edges` data and `unite(node1, node2)`.
53+
1. If there is no vertex with in-degree 2, as soon as `same_root(node1, node2) == true` (a cycle will be formed), return `[node1, node2]`.
54+
1. If there is a vertex with in-degree 2, we need to determine which edge in `two_conflict_edges` should be returned.
55+
See if the graph can form a cycle by not adding the second edge to the graph. If so, return the first edge. Otherwise, return the second edge.
56+
57+
## Complexity
58+
* Time: `O(n)`.
59+
* Space: `O(n)`.
60+
61+
## Python
62+
```python
63+
class Solution:
64+
def __init__(self):
65+
self.parent = None
66+
67+
def findRedundantDirectedConnection(self, edges: List[List[int]]) -> List[int]:
68+
self.parent = list(range(len(edges) + 1))
69+
70+
conflict_edges = two_conflict_edges(edges)
71+
72+
if not conflict_edges:
73+
for x, y in edges:
74+
if self.same_root(x, y):
75+
return [x, y]
76+
77+
self.unite(x, y)
78+
79+
raise Exception('No suitable edge was returned')
80+
81+
for x, y in edges:
82+
if [x, y] == conflict_edges[1]:
83+
continue
84+
85+
if self.same_root(x, y):
86+
return conflict_edges[0]
87+
88+
self.unite(x, y)
89+
90+
return conflict_edges[1]
91+
92+
def unite(self, x, y):
93+
self.parent[y] = x
94+
95+
def find_root(self, node):
96+
if self.parent[node] == node:
97+
return node
98+
99+
return self.find_root(self.parent[node])
100+
101+
def same_root(self, x, y):
102+
return self.find_root(x) == self.find_root(y)
103+
104+
105+
def two_conflict_edges(edges):
106+
conflict_edges = []
107+
child_to_parent = {}
108+
109+
for parent, child in edges:
110+
if child in child_to_parent:
111+
conflict_edges.append([child_to_parent[child], child])
112+
conflict_edges.append([parent, child])
113+
break
114+
115+
child_to_parent[child] = parent
116+
117+
return conflict_edges
118+
```
119+
120+
## Java
121+
```java
122+
// Welcome to create a PR to complete the code of this language, thanks!
123+
```
124+
125+
## Python
126+
```python
127+
// Welcome to create a PR to complete the code of this language, thanks!
128+
```
129+
130+
## C++
131+
```cpp
132+
// Welcome to create a PR to complete the code of this language, thanks!
133+
```
134+
135+
## JavaScript
136+
```javascript
137+
// Welcome to create a PR to complete the code of this language, thanks!
138+
```
139+
140+
## C#
141+
```c#
142+
// Welcome to create a PR to complete the code of this language, thanks!
143+
```
144+
145+
## Go
146+
```go
147+
// Welcome to create a PR to complete the code of this language, thanks!
148+
```
149+
150+
## Ruby
151+
```ruby
152+
# Welcome to create a PR to complete the code of this language, thanks!
153+
```
154+
155+
## C
156+
```c
157+
// Welcome to create a PR to complete the code of this language, thanks!
158+
```
159+
160+
## Kotlin
161+
```kotlin
162+
// Welcome to create a PR to complete the code of this language, thanks!
163+
```
164+
165+
## Swift
166+
```swift
167+
// Welcome to create a PR to complete the code of this language, thanks!
168+
```
169+
170+
## Rust
171+
```rust
172+
// Welcome to create a PR to complete the code of this language, thanks!
173+
```
174+
175+
## Other languages
176+
```
177+
// Welcome to create a PR to complete the code of this language, thanks!
178+
```

0 commit comments

Comments
 (0)