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.

Idea

  • Start from leafs and remove nodes that have only 1 connection
  • Union find - faster

Code

Remove leafs

class Solution:
    def findRedundantConnection(self, edges: List[List[int]]) -> List[int]:
        adj = defaultdict(set)
 
        for a, b in edges:
            adj[a].add(b)
            adj[b].add(a)
 
        # Start from leafs and remove nodes that have only 1 connection
        d = deque(node for node in adj if len(adj[node]) == 1)
        while d:
            node = d.popleft()
            for neighbor in adj[node]:
                adj[neighbor].remove(node)
                if len(adj[neighbor]) == 1:
                    d.append(neighbor)
            del adj[node] 
 
        # Find the last redundant connection
        for a, b in reversed(edges):
            if a in adj and b in adj and b in adj[a]:
                return [a, b]

Union find

class Solution:
    def findRedundantConnection(self, edges: List[List[int]]) -> List[int]:
        root = list(range(len(edges) + 1)) # each node is root of own subtree
 
        def find_root(node):
            if root[node] != node:
                root[node] = find_root(root[node]) # set root for node as root of subtree
            return root[node] # found root of subtree
 
        for node1, node2 in edges: 
            root1, root2 = find_root(node1), find_root(node2)
 
            if root1 == root2:
                return [node1, node2] # both nodes are already in same subtree
 
            root[root2] = root1 # found new connection between nodes / subtrees
            # root[root1] = root2 also works