[LeetCode] 802. Find Eventual Safe States

We start at some node in a directed graph, and every turn, we walk along a directed edge of the graph. If we reach a terminal node (that is, it has no outgoing directed edges), we stop.

We define a starting node to be safe if we must eventually walk to a terminal node. More specifically, there is a natural number k, so that we must have stopped at a terminal node in less than k steps for any choice of where to walk.

Return an array containing all the safe nodes of the graph. The answer should be sorted in ascending order.

The directed graph has n nodes with labels from 0 to n - 1, where n is the length of graph. The graph is given in the following form: graph[i] is a list of labels j such that (i, j) is a directed edge of the graph, going from node i to node j.

 

Example 1:

Illustration of graph

Input: graph = [[1,2],[2,3],[5],[0],[5],[],[]]
Output: [2,4,5,6]
Explanation: The given graph is shown above.

Example 2:

Input: graph = [[1,2,3,4],[1,2],[3,4],[0,4],[]]
Output: [4]

Constraints:

  • n == graph.length
  • 1 <= n <= 104
  • 0 <= graph[i].length <= n
  • graph[i] is sorted in a strictly increasing order.
  • The graph may contain self-loops.
  • The number of edges in the graph will be in the range [1, 4 * 104].

找到最终的安全状态。

在有向图中,以某个节点为起始节点,从该点出发,每一步沿着图中的一条有向边行走。如果到达的节点是终点(即它没有连出的有向边),则停止。

对于一个起始节点,如果从该节点出发,无论每一步选择沿哪条有向边行走,最后必然在有限步内到达终点,则将该起始节点称作是 安全 的。

返回一个由图中所有安全的起始节点组成的数组作为答案。答案数组中的元素应当按 升序 排列。

该有向图有 n 个节点,按 0 到 n - 1 编号,其中 n 是 graph 的节点数。图以下述形式给出:graph[i] 是编号 j 节点的一个列表,满足 (i, j) 是图的一条有向边。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-eventual-safe-states
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

这是一道图论的题,可以有多种思路解决。这里我提供一个 DFS 的做法。题目精简下来其实问的是如果你从图中的每个节点都试图出发,是否有可能在走了若干步之后在某个点就停下了,即停下的点是没有 next 节点的(出度)。题意反过来理解,就是试图找图中从每个点出发是否存在环,把没有环的起点按照升序排列输出即可。因为如果存在环,则这个环上的每个节点都无法找到一个没有出度的节点。

这里我用染色法找环,建立一个和 input 数组等长的 color 数组,里面代表的是每个节点的颜色情况。一开始初始化为 0,说明节点还未被访问过。用 DFS 开始遍历,第一次遇到某个节点,我们把他标记为 2。接着往下递归遍历的时候,遍历过程中检验遇到的节点是否被访问过,如果被访问过(2),说明有环,return false;当前递归结束后,如果一路上都没有再遇到 2,说明这一路上都没有环,可以把当前节点加入结果集,表明从这个点出发的路径可以到达终点。

时间O(n)

空间O(n)

Java实现

 1 class Solution {
 2     public List<Integer> eventualSafeNodes(int[][] graph) {
 3         List<Integer> res = new ArrayList<>();
 4         // corner case
 5         if (graph == null || graph.length == 0) {
 6             return res;
 7         }
 8 
 9         // normal case
10         int count = graph.length;
11         int[] color = new int[count];
12         for (int i = 0; i < count; i++) {
13             if (dfs(graph, i, color)) {
14                 res.add(i);
15             }
16         }
17         return res;
18     }
19 
20     private boolean dfs(int[][] graph, int start, int[] color) {
21         if (color[start] != 0) {
22             return color[start] == 1;
23         }
24         color[start] = 2;
25         for (int next : graph[start]) {
26             if (!dfs(graph, next, color)) {
27                 return false;
28             }
29         }
30         color[start] = 1;
31         return true;
32     }
33 }

 

LeetCode 题目总结

posted @ 2021-08-05 12:27  CNoodle  阅读(112)  评论(0编辑  收藏  举报