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


    题目描述:

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

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

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

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

    解题原理:

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

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

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

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

      1、建图的节点

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

    public class Node {
    int value;
    // 出度
    int in;
    // 入度
    int out;
    // 下个节点
    List<Node> next;

    // key Node 表示:到那个节点的边。
    // value,list表示:节点边的信息,比如:权重之类的
    HashMap<Node,List<Integer>> edgeInfo;

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

      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;
        }
    }
  • 相关阅读:
    【bzoj2242】[SDOI2011]计算器
    1109解题报告
    【bzoj3239】Discrete Logging
    【bzoj2480】Spoj3105 Mod
    【POJ1811】Prime Test
    【bzoj3667】Rabin-Miller算法
    【HDU2138】How many prime numbers
    卢卡斯定理
    线段树2
    畅快的甩卖
  • 原文地址:https://www.cnblogs.com/lxy-java/p/13198060.html
Copyright © 2020-2023  润新知