Skip to content

Commit c24d3fe

Browse files
committed
Added 684-redundant-connection.md in 7 languages' solution.
1 parent 3cd5d63 commit c24d3fe

5 files changed

Lines changed: 383 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,5 +71,6 @@ You can skip the more difficult problems and do them later.
7171
- [827. Making A Large Island](solutions/1-1000/827-making-a-large-island.md) was solved in _Python_.
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.
74+
- [684. Redundant Connection](solutions/1-1000/684-redundant-connection.md) was solved in _Python, Java, C++, JavaScript, C#, Go, Ruby_.
7475

7576
More LeetCode problems will be added soon...

images/684.png

22.2 KB
Loading

images/examples/684_1.jpg

6.78 KB
Loading

images/examples/684_2.jpg

9.51 KB
Loading
Lines changed: 382 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,382 @@
1+
# LeetCode 684. Redundant Connection's Solution
2+
LeetCode problem link: [684. Redundant Connection](https://leetcode.com/problems/redundant-connection)
3+
4+
## LeetCode problem description
5+
In this problem, a tree is an **undirected graph** that is connected and has no cycles.
6+
7+
You are given a graph that started as a tree with `n` nodes labeled from `1` to `n`, with one additional edge added. The added edge has two **different** vertices chosen from `1` to `n`, and was not an edge that already existed. The graph is represented as an array `edges` of length `n` where `edges[i] = [ai, bi]` indicates that there is an edge between nodes `ai` and `bi` in the graph.
8+
9+
Return an edge that can be removed so that the resulting graph is a tree of `n` nodes. If there are multiple answers, return the answer that occurs last in the input.
10+
11+
### Example 1
12+
![](../../images/examples/684_1.jpg)
13+
```
14+
Input: edges = [[1,2],[1,3],[2,3]]
15+
Output: [2,3]
16+
```
17+
18+
### Example 2
19+
![](../../images/examples/684_2.jpg)
20+
```
21+
Input: edges = [[1,2],[2,3],[3,4],[1,4],[1,5]]
22+
Output: [1,4]
23+
```
24+
25+
### Constraints
26+
- `n == edges.length`
27+
- `3 <= n <= 1000`
28+
- `edges[i].length == 2`
29+
- `1 <= ai < bi <= edges.length`
30+
- `ai != bi`
31+
- There are no repeated edges.
32+
- The given graph is connected.
33+
34+
## Intuition
35+
- This undirected graph has only **one** **connected component**, which is a tree.
36+
- When an edge is added to the graph, its two nodes are also added to the graph.
37+
- If the two nodes are already in the graph, then they must be on the same tree. At this time, a cycle is bound to be formed.
38+
39+
![](../../images/684.png)
40+
41+
- We are given `edges` data and need to divide them into multiple groups, each group can be abstracted into a **tree**.
42+
- Finally, those trees will be merged into one tree.
43+
- `UnionFind` algorithm is designed for grouping and searching data.
44+
45+
### 'UnionFind' algorithm
46+
- `UnionFind` algorithm typically has three methods:
47+
- The `unite(node1, node2)` operation can be used to merge two trees.
48+
- The `find_root(node)` method can be used to return the root of a node.
49+
- The `same_root(node1, node2)` method can be used to judge if two nodes are in the same tree.
50+
51+
## Approach (UnionFind algorithm)
52+
1. Initially, each node is in its own group.
53+
1. Iterate `edges` data and `unite(node1, node2)`.
54+
1. As soon as `same_root(node1, node2)`, return `[node1, node2]`.
55+
56+
## Complexity
57+
* Time: `O(n)`.
58+
* Space: `O(n)`.
59+
60+
## Python
61+
```python
62+
class Solution:
63+
def __init__(self):
64+
self.fathers = None
65+
66+
def findRedundantConnection(self, edges: List[List[int]]) -> List[int]:
67+
self.fathers = list(range(len(edges) + 1))
68+
69+
for x, y in edges:
70+
if self.same_root(x, y):
71+
return [x, y]
72+
73+
self.unite(x, y)
74+
75+
def unite(self, x, y):
76+
root_x = self.find_root(x)
77+
root_y = self.find_root(y)
78+
79+
self.fathers[root_y] = root_x # Error-prone point
80+
81+
def find_root(self, x):
82+
if x == self.fathers[x]:
83+
return x
84+
85+
self.fathers[x] = self.find_root(self.fathers[x])
86+
87+
return self.fathers[x]
88+
89+
def same_root(self, x, y):
90+
return self.find_root(x) == self.find_root(y)
91+
```
92+
93+
## Java
94+
```java
95+
class Solution {
96+
private int[] fathers;
97+
98+
public int[] findRedundantConnection(int[][] edges) {
99+
fathers = new int[edges.length + 1];
100+
101+
for (var i = 0; i < fathers.length; i++) {
102+
fathers[i] = i;
103+
}
104+
105+
for (var edge : edges) {
106+
if (sameRoot(edge[0], edge[1])) {
107+
return edge;
108+
}
109+
110+
unite(edge[0], edge[1]);
111+
}
112+
113+
return null;
114+
}
115+
116+
private void unite(int x, int y) {
117+
int rootX = findRoot(x);
118+
int rootY = findRoot(y);
119+
120+
fathers[rootY] = rootX; // Error-prone point 1
121+
}
122+
123+
private int findRoot(int x) {
124+
if (x == fathers[x]) {
125+
return x;
126+
}
127+
128+
fathers[x] = findRoot(fathers[x]); // Error-prone point 2
129+
130+
return fathers[x];
131+
}
132+
133+
private boolean sameRoot(int x, int y) {
134+
return findRoot(x) == findRoot(y);
135+
}
136+
}
137+
```
138+
139+
## C++
140+
```cpp
141+
class Solution {
142+
public:
143+
vector<int> findRedundantConnection(vector<vector<int>>& edges) {
144+
for (auto i = 0; i <= edges.size(); i++) {
145+
fathers.push_back(i);
146+
}
147+
148+
for (auto& edge : edges) {
149+
if (sameRoot(edge[0], edge[1])) {
150+
return edge;
151+
}
152+
153+
unite(edge[0], edge[1]);
154+
}
155+
156+
return {};
157+
}
158+
159+
private:
160+
vector<int> fathers;
161+
162+
void unite(int x, int y) {
163+
int root_x = findRoot(x);
164+
int root_y = findRoot(y);
165+
166+
fathers[root_y] = root_x; // Error-prone point 1
167+
}
168+
169+
int findRoot(int x) {
170+
if (x == fathers[x]) {
171+
return x;
172+
}
173+
174+
fathers[x] = findRoot(fathers[x]); // Error-prone point 2
175+
176+
return fathers[x];
177+
}
178+
179+
bool sameRoot(int x, int y) {
180+
return findRoot(x) == findRoot(y);
181+
}
182+
};
183+
```
184+
185+
## JavaScript
186+
```javascript
187+
let fathers
188+
189+
var findRedundantConnection = function(edges) {
190+
fathers = []
191+
for (let i = 0; i <= edges.length; i++) {
192+
fathers.push(i)
193+
}
194+
195+
for (let [x, y] of edges) {
196+
if (sameRoot(x, y)) {
197+
return [x, y]
198+
}
199+
200+
unite(x, y)
201+
}
202+
203+
return sameRoot(source, destination)
204+
};
205+
206+
function unite(x, y) {
207+
rootX = findRoot(x)
208+
rootY = findRoot(y)
209+
210+
fathers[rootY] = rootX // Error-prone point 1
211+
}
212+
213+
function findRoot(x) {
214+
if (x == fathers[x]) {
215+
return x
216+
}
217+
218+
fathers[x] = findRoot(fathers[x]) // Error-prone point 2
219+
220+
return fathers[x]
221+
}
222+
223+
function sameRoot(x, y) {
224+
return findRoot(x) == findRoot(y)
225+
}
226+
```
227+
228+
## C#
229+
```c#
230+
public class Solution
231+
{
232+
int[] fathers;
233+
234+
public int[] FindRedundantConnection(int[][] edges)
235+
{
236+
fathers = new int[edges.Length + 1];
237+
238+
for (int i = 0; i < fathers.Length; i++)
239+
fathers[i] = i;
240+
241+
foreach (int[] edge in edges)
242+
{
243+
if (sameRoot(edge[0], edge[1]))
244+
{
245+
return edge;
246+
}
247+
248+
unite(edge[0], edge[1]);
249+
}
250+
251+
return null;
252+
}
253+
254+
void unite(int x, int y)
255+
{
256+
int rootX = findRoot(x);
257+
int rootY = findRoot(y);
258+
259+
fathers[rootY] = rootX; // Error-prone point 1
260+
}
261+
262+
int findRoot(int x)
263+
{
264+
if (x == fathers[x])
265+
return x;
266+
267+
fathers[x] = findRoot(fathers[x]); // Error-prone point 2
268+
269+
return fathers[x];
270+
}
271+
272+
bool sameRoot(int x, int y)
273+
{
274+
return findRoot(x) == findRoot(y);
275+
}
276+
}
277+
```
278+
279+
## Go
280+
```go
281+
var fathers []int
282+
283+
func findRedundantConnection(edges [][]int) []int {
284+
fathers = make([]int, len(edges) + 1)
285+
for i := 0; i < len(fathers); i++ {
286+
fathers[i] = i
287+
}
288+
289+
for _, edge := range edges {
290+
if sameRoot(edge[0], edge[1]) {
291+
return edge
292+
}
293+
294+
unite(edge[0], edge[1])
295+
}
296+
297+
return nil
298+
}
299+
300+
func unite(x, y int) {
301+
rootX := findRoot(x)
302+
rootY := findRoot(y)
303+
304+
fathers[rootY] = rootX // Error-prone point 1
305+
}
306+
307+
func findRoot(x int) int {
308+
if x == fathers[x] {
309+
return x
310+
}
311+
312+
fathers[x] = findRoot(fathers[x]) // Error-prone point 2
313+
314+
return fathers[x]
315+
}
316+
317+
func sameRoot(x, y int) bool {
318+
return findRoot(x) == findRoot(y)
319+
}
320+
```
321+
322+
## Ruby
323+
```ruby
324+
def find_redundant_connection(edges)
325+
@fathers = []
326+
(0..edges.size).each { |i| @fathers << i }
327+
328+
edges.each do |edge|
329+
if same_root(edge[0], edge[1])
330+
return edge
331+
end
332+
333+
unite(edge[0], edge[1])
334+
end
335+
end
336+
337+
def unite(x, y)
338+
root_x = find_root(x)
339+
root_y = find_root(y)
340+
341+
@fathers[root_y] = root_x # Error-prone point 1
342+
end
343+
344+
def find_root(x)
345+
if x == @fathers[x]
346+
return x
347+
end
348+
349+
@fathers[x] = find_root(@fathers[x]) # Error-prone point 2
350+
351+
@fathers[x]
352+
end
353+
354+
def same_root(x, y)
355+
find_root(x) == find_root(y)
356+
end
357+
```
358+
359+
## C
360+
```c
361+
// Welcome to create a PR to complete the code of this language, thanks!
362+
```
363+
364+
## Kotlin
365+
```kotlin
366+
// Welcome to create a PR to complete the code of this language, thanks!
367+
```
368+
369+
## Swift
370+
```swift
371+
// Welcome to create a PR to complete the code of this language, thanks!
372+
```
373+
374+
## Rust
375+
```rust
376+
// Welcome to create a PR to complete the code of this language, thanks!
377+
```
378+
379+
## Other languages
380+
```
381+
// Welcome to create a PR to complete the code of this language, thanks!
382+
```

0 commit comments

Comments
 (0)