Find Eventual Safe States

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

Now, say our starting node is eventually safe if and only if we must eventually walk to a terminal node.  More specifically, there exists a natural number K so that for any choice of where to walk, we must have stopped at a terminal node in less than K steps.

Which nodes are eventually safe?  Return them as an array in sorted order.

The directed graph has N nodes with labels 0, 1, ..., 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.

Example:
Input: graph = [[1,2],[2,3],[5],[0],[5],[],[]]
Output: [2,4,5,6]
Here is a diagram of the above graph.

Illustration of graph

思路:从每个点开始做dfs,只有每条路都是通往safe的点,那么这个点就是safe的,只要有一条是有cycle的,这题巧妙的地方是不仅仅是看是否有环,而是看状态,如果有环有时候不行,有时候是可以的;所以这题不能用hashset来detect是否有环,得用状态来表示;

         1

     /         \

2      ->      3      ->       4 

上面的图2,3,4是safe的,实际上1也是safe的,因为1的neighbor虽然visite过了,但是neighbor都是safe的;

class Solution {
    public List<Integer> eventualSafeNodes(int[][] graph) {
        List<Integer> list = new ArrayList<Integer>();
        // 0, unvisited;
        // 1, safe;
        // 2, unsafe;
        int n = graph.length;
        int[] status = new int[n];
        for(int i = 0; i < n; i++) {
            if(dfs(graph, i, status)) {
                list.add(i);
            }
        }
        return list;
    }
    
    private boolean dfs(int[][] graph, int node, int[] status) {
        if(status[node] != 0) { // 这里用状态来表示,有可能之前visite过了,但是是safe的;
            return status[node] == 1;
        }
        status[node] = 2; // 每次默认是unsafe;
        for(Integer neighbor: graph[node]) {
            if(!dfs(graph, neighbor, status)) {
                return false;
            }
        }
        status[node] = 1; // 经过检测之后,neighbor都是safe,那么才赋值safe;
        return true;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值