LeetCode每日一题:802 找到最终安全状态

题目描述:

  在有向图中,我们从某个节点出发和每个转向出开始,沿着有向图的边走。如果我们到达的节点是终点(即它没有连出的有向边),我们停止

  现在,如果我们最后能走到终点,那么我们的起始节点是最终安全的。更具体的说,存在一个自然数k,无论选择从哪里开始行走,我们走了不

  到k步必能停止在一个终点。

  那些节点是安全的?返回一个有序的数组

解题原理:

  这道题的实质:就是从一个节点出发,看沿路有没有环

一、先说一个解决图问题的模板套路

  该套路不能在LeetCode中通过该题,时间主要浪费在了建图上。

  但是,图的题一般不会出现在面试中,笔试中较为常见。该模板可以解决这一系列问题。平时练习熟悉,笔试套用即可。

  1、建图的节点

import java.util.ArrayList;
import java.util.List;

public class Node {
    int value;
//    出度
    int in;
//    入度
    int out;
//    下个节点
    List<Node> next;
//    节点边的信息,比如:权重之类的
    List<Integer> edgeInfo;

    public Node(int value){
        this.value = value;
        next = new ArrayList<>();
        edgeInfo = new ArrayList<>();
    }
}

  2、根据题目建图,一般题目给的是矩阵。以该题为例

private HashMap<Integer,Node> createGraph(int[][] graph){
    HashMap<Integer,Node> nodes = new HashMap<>();
    for(int i=0;i<graph.length;i++){
        Node a = null;
        if(nodes.containsKey(i)){
            a = nodes.get(i);
        }else{
            a = new Node(i);
            nodes.put(i,a);
        }
        for(int j=0;j<graph[i].length;j++){
            Node b = null;
            if(nodes.containsKey(graph[i][j])){
                b = nodes.get(graph[i][j]);
            }else{
                b = new Node(graph[i][j]);
                nodes.put(graph[i][j],b);
            }
            a.nexts.add(b);
        }
    }
    return nodes;
}

  3、根据深度优先遍历判断有环无环

// 0表示该节点还没有被访问过,1表示该节点正在访问中,2表示该节点被访问过。
    private boolean dfs(Node a,int[] color){
        if(a==null){
            return true;
        }
        if(color[a.value]==1){
            return false;
        }
        color[a.value] = 1;
        for(Node next : a.nexts){  
            if(color[next.value]==1){
                return false;
            }         
            if(!dfs(next,color)){
                return false;
            }
            color[next.value] = 2;
        }
        return true;
    }

  4、选出符合题意的节点

public List<Integer> eventualSafeNodes(int[][] graph) {
        HashMap<Integer,Node> nodes = createGraph(graph);
        List<Integer> result = new ArrayList<>();
        for(int key : nodes.keySet()){
            Node head = nodes.get(key);
            if(dfs(head,new int[nodes.size()])) {
                result.add(head.value);
            }
        }
        return result;
    }

二、LeetCode官方解

class Solution {
    /**
        说明:我拿的官方答案过得,官方答案跟我的区别是:
            官方直接在矩阵上操作,而我用HashMap建图,时间主要浪费在了建图上
            dfs那部分跟官方一样。时间复杂度都一样
    */
    public List<Integer> eventualSafeNodes(int[][] graph) {
        int N = graph.length;
        int[] color = new int[N];
        List<Integer> ans = new ArrayList();

        for (int i = 0; i < N; ++i)
            if (dfs(i, color, graph))
                ans.add(i);
        return ans;
    }

    // colors: WHITE 0, GRAY 1, BLACK 2;
    public boolean dfs(int node, int[] color, int[][] graph) {
        if (color[node] > 0)
            return color[node] == 2;

        color[node] = 1;
        for (int nei: graph[node]) {
            if (color[node] == 2)
                continue;
            if (color[nei] == 1 || !dfs(nei, color, graph))
                return false;
        }

        color[node] = 2;
        return true;
    }
}

猜你喜欢

转载自www.cnblogs.com/lxy-java/p/13198060.html