冗余连接 II
难度:
标签:
题目描述
在本问题中,有根树指满足以下条件的 有向 图。该树只有一个根节点,所有其他节点都是该根节点的后继。该树除了根节点之外的每一个节点都有且只有一个父节点,而根节点没有父节点。
输入一个有向图,该图由一个有着 n
个节点(节点值不重复,从 1
到 n
)的树及一条附加的有向边构成。附加的边包含在 1
到 n
中的两个不同顶点间,这条附加的边不属于树中已存在的边。
结果图是一个以边组成的二维数组 edges
。 每个元素是一对 [ui, vi]
,用以表示 有向 图中连接顶点 ui
和顶点 vi
的边,其中 ui
是 vi
的一个父节点。
返回一条能删除的边,使得剩下的图是有 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
代码结果
运行时间: 28 ms, 内存: 16.4 MB
// Problem: Given a directed graph with n nodes, represented as an edge list, where the nodes are numbered from 1 to n. The graph is initially a tree, with one additional edge added that causes a cycle or multiple parents. Our task is to find and return one edge that can be removed to form a valid tree with one root and no cycles.
// Approach using Java Streams:
// 1. Use an array to track the parent of each node.
// 2. Traverse the edge list and detect a cycle or a node with two parents.
// 3. If a cycle is detected, return the last edge that causes it.
// 4. If a node has two parents, return the second edge encountered.
import java.util.Arrays;
import java.util.stream.IntStream;
public class Solution {
public int[] findRedundantDirectedConnection(int[][] edges) {
int n = edges.length;
int[] parent = new int[n + 1];
int[] candidate1 = null, candidate2 = null;
Arrays.fill(parent, 0);
for (int[] edge : edges) {
int u = edge[0], v = edge[1];
if (parent[v] == 0) {
parent[v] = u;
} else {
candidate1 = new int[]{parent[v], v};
candidate2 = new int[]{u, v};
edge[1] = 0;
}
}
IntStream.range(1, n + 1).forEach(i -> parent[i] = i);
for (int[] edge : edges) {
if (edge[1] == 0) continue;
int u = edge[0], v = edge[1];
if (find(parent, u) == v) {
return candidate1 == null ? edge : candidate1;
}
parent[v] = u;
}
return candidate2;
}
private int find(int[] parent, int u) {
return parent[u] == u ? u : (parent[u] = find(parent, parent[u]));
}
}
解释
方法:
该题解使用并查集来解决问题。首先预处理边的入度数组,记录每个节点被指向的次数。然后按照特定顺序尝试删除边,判断删除后的图是否会形成环。如果删除构成入度为2的边不会形成环,说明这条边是导致冗余的边;如果删除构成入度为1的边不会形成环,说明这条边是导致冗余的边。在并查集中,如果合并两个节点时发现它们已经在同一个集合内,说明形成了环。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
在题解中提到的并查集中的`路径压缩`技术是如何帮助优化查找效率的?
▷🦆
题解中未详细解释如何处理入度为2的节点的两条边,具体是如何判断哪一条边应当被删除以解决冗余连接问题?
▷🦆
在使用并查集判断形成环的逻辑中,为何合并操作返回False表示已经形成环,这背后的逻辑是什么?
▷🦆
题解中提到删除某条边后判断是否形成环,这一步骤在实现上是如何确保删除的边确实不被考虑在内的?
▷相关问题
冗余连接
树可以看成是一个连通且 无环 的 无向 图。
给定往一棵 n
个节点 (节点值 1~n
) 的树中添加一条边后的图。添加的边的两个顶点包含在 1
到 n
中间,且这条附加的边不属于树中已存在的边。图的信息记录于长度为 n
的二维数组 edges
,edges[i] = [ai, bi]
表示图中在 ai
和 bi
之间存在一条边。
请找出一条可以删去的边,删除后可使得剩余部分是一个有着 n
个节点的树。如果有多个答案,则返回数组 edges
中最后出现的那个。
示例 1:
输入: edges = [[1,2], [1,3], [2,3]] 输出: [2,3]
示例 2:
输入: edges = [[1,2], [2,3], [3,4], [1,4], [1,5]] 输出: [1,4]
提示:
n == edges.length
3 <= n <= 1000
edges[i].length == 2
1 <= ai < bi <= edges.length
ai != bi
edges
中无重复元素- 给定的图是连通的