LeetCode 题解工作台

冗余连接 II

在本问题中,有根树指满足以下条件的 有向 图。该树只有一个根节点,所有其他节点都是该根节点的后继。该树除了根节点之外的每一个节点都有且只有一个父节点,而根节点没有父节点。 输入一个有向图,该图由一个有着 n 个节点(节点值不重复,从 1 到 n )的树及一条附加的有向边构成。附加的边包含在 1 到 …

category

4

题型

code_blocks

6

代码语言

hub

3

相关题

当前训练重点

困难 · 图·DFS·traversal

bolt

答案摘要

根据题目描述,对于一棵有根树,根节点的入度为 ,其余节点的入度为 。在向树中添加一条边之后,可能会出现以下三种情况: 1. 添加的边指向了非根节点,该节点的入度变为 ,此时图中不存在有向环;

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 图·DFS·traversal 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

在本问题中,有根树指满足以下条件的 有向 图。该树只有一个根节点,所有其他节点都是该根节点的后继。该树除了根节点之外的每一个节点都有且只有一个父节点,而根节点没有父节点。

输入一个有向图,该图由一个有着 n 个节点(节点值不重复,从 1n)的树及一条附加的有向边构成。附加的边包含在 1n 中的两个不同顶点间,这条附加的边不属于树中已存在的边。

结果图是一个以边组成的二维数组 edges 。 每个元素是一对 [ui, vi],用以表示 有向 图中连接顶点 ui 和顶点 vi 的边,其中 uivi 的一个父节点。

返回一条能删除的边,使得剩下的图是有 n 个节点的有根树。若有多个答案,返回最后出现在给定二维数组的答案。

 

示例 1:

输入:edges = [[1,2],[1,3],[2,3]]
输出:[2,3]

示例 2:

输入:edges = [[1,2],[2,3],[3,4],[4,1],[1,5]]
输出:[4,1]

 

提示:

  • n == edges.length
  • 3 <= n <= 1000
  • edges[i].length == 2
  • 1 <= ui, vi <= n
lightbulb

解题思路

方法一:并查集

根据题目描述,对于一棵有根树,根节点的入度为 00,其余节点的入度为 11。在向树中添加一条边之后,可能会出现以下三种情况:

  1. 添加的边指向了非根节点,该节点的入度变为 22,此时图中不存在有向环;

       1
      / \
     v   v
     2-->3
    
  2. 添加的边指向了非根节点,该节点的入度变为 22,此时图中存在有向环;

       1
       |
       v
       2 <--> 3
    
  3. 添加的边指向了根节点,根节点的入度变为 11,此时图中存在有向环,但不存在入度为 22 的节点。

        1
        /^
       v  \
       2-->3
    

因此,我们首先计算每个节点的入度,如果存在入度为 22 的节点,我们定位到该节点对应的两条边,分别记为 dup[0]\textit{dup}[0]dup[1]\textit{dup}[1]。如果在删除 dup[1]\textit{dup}[1] 之后,剩余的边无法形成树,则说明 dup[0]\textit{dup}[0] 是需要删除的边;否则 dup[1]\textit{dup}[1] 是需要删除的边。

如果不存在入度为 22 的节点,我们遍历数组 edges\textit{edges},对于每条边 (u,v)(u, v),我们使用并查集维护节点之间的连通性。如果 uuvv 已经连通,说明图中存在有向环,此时当前边即为需要删除的边。

时间复杂度 O(nlogn)O(n \log n),空间复杂度 O(n)O(n)。其中 nn 为边的数量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Solution:
    def findRedundantDirectedConnection(self, edges: List[List[int]]) -> List[int]:
        def find(x: int) -> int:
            if p[x] != x:
                p[x] = find(p[x])
            return p[x]

        n = len(edges)
        ind = [0] * n
        for _, v in edges:
            ind[v - 1] += 1
        dup = [i for i, (_, v) in enumerate(edges) if ind[v - 1] == 2]
        p = list(range(n))
        if dup:
            for i, (u, v) in enumerate(edges):
                if i == dup[1]:
                    continue
                pu, pv = find(u - 1), find(v - 1)
                if pu == pv:
                    return edges[dup[0]]
                p[pu] = pv
            return edges[dup[1]]
        for i, (u, v) in enumerate(edges):
            pu, pv = find(u - 1), find(v - 1)
            if pu == pv:
                return edges[i]
            p[pu] = pv
speed

复杂度分析

指标
时间O(N)
空间O(N)
psychology

面试官常问的追问

外企场景
  • question_mark

    The candidate uses an efficient cycle detection algorithm like DFS or Union-Find.

  • question_mark

    The candidate is able to explain the graph traversal approach clearly and apply it correctly.

  • question_mark

    The candidate identifies and removes the redundant edge without unnecessary computation.

warning

常见陷阱

外企场景
  • error

    Not properly tracking the visited nodes, leading to incorrect cycle detection.

  • error

    Confusing Union-Find operations, such as not correctly implementing union and find operations.

  • error

    Failing to handle edge cases where the graph has only a single redundant connection.

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    Graph with multiple redundant edges (not allowed in this problem but can be extended to handle).

  • arrow_right_alt

    Using BFS instead of DFS for traversal and cycle detection.

  • arrow_right_alt

    Handling larger graphs with optimizations in both space and time complexity.

help

常见问题

外企场景

冗余连接 II题解:图·DFS·traversal | LeetCode #685 困难