深度优先

802.找到最终的安全状态

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

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

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

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

提示:

  • n == graph.length
  • 1 <= n <= 104
  • 0 <= graph[i].length <= n
  • graph[i] 按严格递增顺序排列。
  • 图中可能包含自环。
  • 图中边的数目在范围 [1, 4 * 104] 内。

思路:深度遍历 + 三色标记
1.当一个节点位于环内,则这个节点不安全
2.三色标记:0未访问/1位于递归栈中or不安全/2安全节点

当我们首次访问一个节点时,将其标记为灰色,并继续搜索与其相连的节点。

如果在搜索过程中遇到了一个灰色节点,则说明找到了一个环,此时退出搜索,栈中的节点仍保持为灰色,这一做法可以将「找到了环」这一信息传递到栈中的所有节点上。

如果搜索过程中没有遇到灰色节点,则说明没有遇到环,那么递归返回前,我们将其标记由灰色改为黑色,即表示它是一个安全的节点。

class Solution {
    public List<Integer> eventualSafeNodes(int[][] graph) {
        List<Integer> res = new ArrayList();
        if(graph == null || graph.length == 0) return res;
        int n = graph.length;
        int[] color = new int[n];
        for(int i = 0 ; i < n ; i++){
            if(isSafe(graph,color,i)){
                res.add(i);
            }
        }
        return res;
    }

    private boolean isSafe(int[][] graph , int[] color , int p){
        if(color[p] > 0){    //当前节点已访问过
            return color[p] == 2;
        }
        color[p] = 1;        //第一次访问当前节点
        for(int q : graph[p]){    //深度优先遍历
            if(!isSafe(graph , color , q)){    //访问到不安全节点,说明当前节点在环内
                return false;
            }
        }
        color[p] = 2;        //当前节点的所有边都安全,标记当前节点为安全
        return true;

    }
}
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务