受限条件下可到达节点的数目
难度:
标签:
题目描述
现有一棵由 n
个节点组成的无向树,节点编号从 0
到 n - 1
,共有 n - 1
条边。
给你一个二维整数数组 edges
,长度为 n - 1
,其中 edges[i] = [ai, bi]
表示树中节点 ai
和 bi
之间存在一条边。另给你一个整数数组 restricted
表示 受限 节点。
在不访问受限节点的前提下,返回你可以从节点 0
到达的 最多 节点数目。
注意,节点 0
不 会标记为受限节点。
示例 1:

输入:n = 7, edges = [[0,1],[1,2],[3,1],[4,0],[0,5],[5,6]], restricted = [4,5] 输出:4 解释:上图所示正是这棵树。 在不访问受限节点的前提下,只有节点 [0,1,2,3] 可以从节点 0 到达。
示例 2:

输入:n = 7, edges = [[0,1],[0,2],[0,5],[0,4],[3,2],[6,5]], restricted = [4,2,1] 输出:3 解释:上图所示正是这棵树。 在不访问受限节点的前提下,只有节点 [0,5,6] 可以从节点 0 到达。
提示:
2 <= n <= 105
edges.length == n - 1
edges[i].length == 2
0 <= ai, bi < n
ai != bi
edges
表示一棵有效的树1 <= restricted.length < n
1 <= restricted[i] < n
restricted
中的所有值 互不相同
代码结果
运行时间: 123 ms, 内存: 59.6 MB
// Java Stream solution
// 思路:
// 虽然Java Stream更适合数据流处理,但我们依然可以通过组合多个Stream操作来实现DFS。
// 不过,由于DFS涉及到递归或显式的栈操作,Stream的优势并不明显。
// 这里我们主要还是利用Stream对集合进行过滤和遍历。
import java.util.*;
import java.util.stream.*;
public class Solution {
public int reachableNodes(int n, int[][] edges, int[] restricted) {
List<List<Integer>> graph = IntStream.range(0, n)
.mapToObj(i -> new ArrayList<Integer>())
.collect(Collectors.toList());
for (int[] edge : edges) {
graph.get(edge[0]).add(edge[1]);
graph.get(edge[1]).add(edge[0]);
}
Set<Integer> restrictedSet = Arrays.stream(restricted).boxed().collect(Collectors.toSet());
boolean[] visited = new boolean[n];
return dfs(0, graph, visited, restrictedSet);
}
private int dfs(int node, List<List<Integer>> graph, boolean[] visited, Set<Integer> restrictedSet) {
if (restrictedSet.contains(node) || visited[node]) {
return 0;
}
visited[node] = true;
return 1 + graph.get(node).stream()
.filter(neighbor -> !visited[neighbor] && !restrictedSet.contains(neighbor))
.mapToInt(neighbor -> dfs(neighbor, graph, visited, restrictedSet))
.sum();
}
}
解释
方法:
题解采用了深度优先搜索(DFS)的方法来解决该问题。首先,通过使用图(以邻接表的形式)来表示树的结构,从而避免访问受限节点。然后,从节点0开始,递归地遍历所有可到达的节点,并计算可到达节点的总数。在建图过程中,如果边的任一端点是受限节点,则该边不被添加到图中。DFS函数通过递归的方式访问所有子节点(排除了父节点以防止返回),并累计可以到达的节点数。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
在构建图时,为什么选择邻接表而不是邻接矩阵来表示树的结构?
▷🦆
如何确保DFS过程中不会重复访问已经访问过的节点?
▷🦆
在DFS函数中,`fa`参数的作用是什么?为什么需要有这个参数?
▷