684. Redundant Connection
Problem Description
In this problem, a tree is an undirected graph that is connected and has no cycles.
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.
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.
Examples:
Example 1:
Input: edges = [[1,2],[1,3],[2,3]] Output: [2,3]
Example 2:
Input: edges = [[1,2],[2,3],[3,4],[1,4],[1,5]] Output: [1,4]
Constraints:
- n == edges.length
- 3 ≤ n ≤ 1000
- edges[i].length == 2
- 1 ≤ ai < bi ≤ edges.length
- ai != bi
- There are no repeated edges
- The given graph is connected
Python Solution
class Solution:
def findRedundantConnection(self, edges: List[List[int]]) -> List[int]:
parent = list(range(len(edges) + 1))
def find(x):
if parent[x] != x:
parent[x] = find(parent[x])
return parent[x]
def union(x, y):
parent[find(x)] = find(y)
for edge in edges:
if find(edge[0]) == find(edge[1]):
return edge
union(edge[0], edge[1])
return []
Implementation Notes:
- Uses Union-Find (Disjoint Set) data structure
- Time complexity: O(N) where N is the number of edges
- Space complexity: O(N)
- Path compression optimization in find operation
Java Solution
class Solution {
private int[] parent;
public int[] findRedundantConnection(int[][] edges) {
parent = new int[edges.length + 1];
for (int i = 0; i <= edges.length; i++) {
parent[i] = i;
}
for (int[] edge : edges) {
if (find(edge[0]) == find(edge[1])) {
return edge;
}
union(edge[0], edge[1]);
}
return new int[]{};
}
private int find(int x) {
if (parent[x] != x) {
parent[x] = find(parent[x]);
}
return parent[x];
}
private void union(int x, int y) {
parent[find(x)] = find(y);
}
}
C++ Solution
class Solution {
private:
vector parent;
int find(int x) {
if (parent[x] != x) {
parent[x] = find(parent[x]);
}
return parent[x];
}
void union_set(int x, int y) {
parent[find(x)] = find(y);
}
public:
vector findRedundantConnection(vector>& edges) {
parent.resize(edges.size() + 1);
for (int i = 0; i <= edges.size(); i++) {
parent[i] = i;
}
for (const auto& edge : edges) {
if (find(edge[0]) == find(edge[1])) {
return edge;
}
union_set(edge[0], edge[1]);
}
return {};
}
};
JavaScript Solution
/**
* @param {number[][]} edges
* @return {number[]}
*/
var findRedundantConnection = function(edges) {
const parent = Array.from({length: edges.length + 1}, (_, i) => i);
const find = (x) => {
if (parent[x] !== x) {
parent[x] = find(parent[x]);
}
return parent[x];
};
const union = (x, y) => {
parent[find(x)] = find(y);
};
for (const [x, y] of edges) {
if (find(x) === find(y)) {
return [x, y];
}
union(x, y);
}
return [];
};
C# Solution
public class Solution {
private int[] parent;
public int[] FindRedundantConnection(int[][] edges) {
parent = new int[edges.Length + 1];
for (int i = 0; i <= edges.Length; i++) {
parent[i] = i;
}
foreach (var edge in edges) {
if (Find(edge[0]) == Find(edge[1])) {
return edge;
}
Union(edge[0], edge[1]);
}
return new int[]{};
}
private int Find(int x) {
if (parent[x] != x) {
parent[x] = Find(parent[x]);
}
return parent[x];
}
private void Union(int x, int y) {
parent[Find(x)] = Find(y);
}
}
Implementation Notes:
- Uses Union-Find data structure with path compression
- Time complexity: O(N) where N is the number of edges
- Space complexity: O(N)
- Returns the last edge that creates a cycle