Given a connected undirected graph with n
nodes (labeled from 1
to n
). You are tasked with finding an edge that, when removed, will result in a tree (that is, the graph will have no cycles). If there are multiple answers, return the edge that occurs last in the given input. The input edges are given as a 2D array edges
where each element is a pair of nodes that form an edge in the graph.
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]
n
?
n
is between 3
and 1000
.[1, n]
.To solve this problem, we’ll use the Union-Find (Disjoint Set) data structure to detect cycles in the graph. The Union-Find structure supports two main operations efficiently:
If, while processing the edges, we find that adding an edge forms a cycle, this edge is the redundant one.
Here are the steps:
class UnionFind:
def __init__(self, size):
self.parent = list(range(size))
self.rank = [1] * size
def find(self, x):
if x != self.parent[x]:
self.parent[x] = self.find(self.parent[x]) # Path compression
return self.parent[x]
def union(self, x, y):
rootX = self.find(x)
rootY = self.find(y)
if rootX != rootY:
# Union by rank
if self.rank[rootX] > self.rank[rootY]:
self.parent[rootY] = rootX
elif self.rank[rootX] < self.rank[rootY]:
self.parent[rootX] = rootY
else:
self.parent[rootY] = rootX
self.rank[rootX] += 1
return True
else:
return False
def findRedundantConnection(edges):
n = len(edges)
uf = UnionFind(n + 1) # n+1 to handle 1-indexed nodes
for u, v in edges:
if not uf.union(u, v):
return [u, v]
find
and union
operations in the Union-Find structure have an amortized time complexity of nearly O(1), thanks to path compression and union by rank.Therefore, the overall time complexity of this solution is O(E), which is efficient given the constraints.
Got blindsided by a question you didn’t expect?
Spend too much time studying?
Or simply don’t have the time to go over all 3000 questions?