当前位置:   article > 正文

【Leetcode】802. 找到最终的安全状态

找到最终的安全状态

题目描述

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

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

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

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

来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/find-eventual-safe-states

示例1
有向图
输入:graph = [[1,2],[2,3],[5],[0],[5],[],[]]
输出:[2,4,5,6]
解释:示意图如上。

示例2
输入:graph = [[1,2,3,4],[1,2],[3,4],[0,4],[]]
输出:[4]

提示

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

解题思路

方法1:深度优先搜索+三色标记

根据题意,若起始节点位于一个环内,或者能到达一个环,则该节点不是安全的。否则,该节点是安全的。我们可以使用深度优先搜索来找环,并在深度优先搜索时,用三种颜色对节点进行标记,标记的规则如下:

  • 白色(用 0 表示):该节点尚未被访问;
  • 灰色(用 1 表示):该节点位于递归栈中,或者在某个环上;
  • 黑色(用 2 表示):该节点搜索完毕,是一个安全节点。

搜索的具体过程如下:
(1)当我们首次访问一个节点时,将其标记为灰色,并继续搜索与其相连的节点。
(2)如果在搜索过程中遇到了一个灰色节点,则说明找到了一个环,此时退出搜索,栈中的节点仍保持为灰色,这一做法可以将「找到了环」这一信息传递到栈中的所有节点上。
(3)如果搜索过程中没有遇到灰色节点,则说明没有遇到环,那么递归返回前,我们将其标记由灰色改为黑色,即表示它是一个安全的节点。
代码如下

package com.jz.day1128;

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

/**
 * 802. 找到最终的安全状态
 */
public class EventualSafeNodes {
    public List<Integer> eventualSafeNodes(int[][] graph) {
        int n = graph.length;
        int[] color = new int[n];
        List<Integer> res = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            if (safe(graph, color, i)) {
                res.add(i);
            }
        }
        return res;
    }

    public boolean safe(int[][] graph, int[] color, int x) {
        if (color[x] > 0) {
            return color[x] == 2;
        }
        color[x] = 1;
        for (int y : graph[x]) {
            if (!safe(graph, color, y)) {
                return false;
            }
        }
        color[x] = 2;
        return true;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

复杂度分析

  • 时间复杂度:O(n+m),其中 n 是图中的点数,m 是图中的边数。
  • 空间复杂度:O(n)。存储节点颜色以及递归栈的开销均为 O(n)。

方法2:拓扑排序

根据题意,若一个节点没有出边,则该节点是安全的;若一个节点出边相连的点都是安全的,则该节点也是安全的。根据这一性质,我们可以将图中所有边反向,得到一个反图,然后在反图上运行拓扑排序

具体来说,首先得到反图 rg \textit{rg} rg 及其入度数组 inDeg \textit{inDeg} inDeg将所有入度为 0 的点加入队列,然后不断取出队首元素,将其出边相连的点的入度减一,若该点入度减一后为 0,则将该点加入队列,如此循环直至队列为空。循环结束后,所有入度为 0 的节点均为安全的。我们遍历入度数组,并将入度为 0 的点加入答案列表。
代码如下

    public List<Integer> eventualSafeNodes2(int[][] graph) {
        int n = graph.length;
        List<List<Integer>> rg = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            rg.add(new ArrayList<>());
        }
        int[] inDeg = new int[n]; // 入度数组
        for (int x = 0; x < n; x++) {
            for (int y : graph[x]) {
                rg.get(y).add(x);
            }
            inDeg[x] = graph[x].length;
        }
        Queue<Integer> queue = new LinkedList<>();
        for (int i = 0; i < n; i++) {
            if (inDeg[i]==0){
                queue.offer(i);
            }
        }
        while (!queue.isEmpty()) {
            int y = queue.poll();
            for (int x : rg.get(y)) {
                if (--inDeg[x] == 0) {
                    queue.offer(x);
                }
            }
        }
        List<Integer> ans = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            if (inDeg[i] == 0) {
                ans.add(i);
            }
        }
        return ans;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

复杂度分析

  • 时间复杂度:O(n+m),其中 n 是图中的点数,m 是图中的边数。
  • 空间复杂度:O(n+m)。需要 O(n+m) 的空间记录反图。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/995266
推荐阅读
相关标签
  

闽ICP备14008679号