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.

Note:

  • graph will have length at most 10000.
  • The number of edges in the graph will not exceed 32000.
  • Each graph[i] will be a sorted list of different integers, chosen within the range [0, graph.length - 1].

在一个有向图中,如果从一个节点出发走过很多步之后到达了终点(出度为0的节点,无路可走了),则认为这个节点是最终安全的节点。如果根本停不下来,那就是在一个环上,就是不安全节点。要在自然数K步内停止,到达安全节点,返回满足要求的排序好的所有安全节点的索引值。实质是在一个有向图中找出不在环路上的节点。

解法:DFS,可采用染色的方法对节点进行分类:0表示该结点还没有被访问;1表示已经被访问过了,并且发现是safe的;2表示被访问过了,但发现是unsafe的。我们采用DFS的方法进行遍历,并返回该结点是否是safe的:如果发现它已经被访问过了,则直接返回是否是safe的标记;否则就首先将其标记为unsafe的,然后进行DFS搜索(此时该结点会处在DFS的路径上,所以后面的DFS一旦到了该结点,就会被认为是形成了环,所以直接返回false)。当整个DFS的搜索都已经结束,并且都没有发现该结点处在环上时,说明该结点是safe的,所以此时将其最终标记为safe即可。空间复杂度是O(n),时间复杂度是O(n)

解法2: 迭代,记录下每个节点的出度,如果出度为0那必然是环路外的节点,然后将该点以及指向该点的边删除,继续寻找出度为0的点

class Solution {
public List<Integer> eventualSafeNodes(int[][] graph) {
List<Integer> res = new ArrayList<>();
if(graph == null || graph.length == 0) return res; int nodeCount = graph.length;
int[] color = new int[nodeCount]; for(int i = 0;i < nodeCount;i++){
if(dfs(graph, i, color)) res.add(i);
} return res;
}
public boolean dfs(int[][] graph, int start, int[] color){
if(color[start] != 0) return color[start] == 1; color[start] = 2;
for(int newNode : graph[start]){
if(!dfs(graph, newNode, color)) return false;
}
color[start] = 1; return true;
}
}

Python:

def eventualSafeNodes(self, graph):
"""
:type graph: List[List[int]]
:rtype: List[int]
"""
n = len(graph)
out_degree = collections.defaultdict(int)
in_nodes = collections.defaultdict(list)
queue = []
ret = []
for i in range(n):
out_degree[i] = len(graph[i])
if out_degree[i]==0:
queue.append(i)
for j in graph[i]:
in_nodes[j].append(i)
while queue:
term_node = queue.pop(0)
ret.append(term_node)
for in_node in in_nodes[term_node]:
out_degree[in_node] -= 1
if out_degree[in_node]==0:
queue.append(in_node)
return sorted(ret)

Python:

# Time:  O(|V| + |E|)
# Space: O(|V|)
import collections class Solution(object):
def eventualSafeNodes(self, graph):
"""
:type graph: List[List[int]]
:rtype: List[int]
"""
WHITE, GRAY, BLACK = 0, 1, 2 def dfs(graph, node, lookup):
if lookup[node] != WHITE:
return lookup[node] == BLACK
lookup[node] = GRAY
for child in graph[node]:
if lookup[child] == BLACK:
continue
if lookup[child] == GRAY or \
not dfs(graph, child, lookup):
return False
lookup[node] = BLACK
return True lookup = collections.defaultdict(int)
return filter(lambda node: dfs(graph, node, lookup), xrange(len(graph)))

Python:

class Solution(object):
def eventualSafeNodes(self, graph):
"""
:type graph: List[List[int]]
:rtype: List[int]
"""
if not graph: return [] n = len(graph)
# 用字段存储每个节点的父节点
d = {u:[] for u in range(n)}
degree = [0] * n
for u in range(n):
for v in graph[u]:
d[v].append(u)
degree[u] = len(graph[u]) Q = [u for u in range(n) if degree[u]==0]
res = []
while Q:
node = Q.pop()
res.append(node)
for nodes in d[node]:
degree[nodes] -= 1
if degree[nodes] == 0:
Q.append(nodes)
return sorted(res) 

C++:

class Solution {
public:
vector<int> eventualSafeNodes(vector<vector<int>>& graph) {
vector<int> res;
if (graph.size() == 0) {
return res;
}
int size = graph.size();
vector<int> color(size, 0); // 0: not visited; 1: safe; 2: unsafe.
for (int i = 0; i < size; ++i) {
if (dfs(graph, i, color)) { // the i-th node is safe
res.push_back(i);
}
}
return res;
}
private:
bool dfs(vector<vector<int>> &graph, int start, vector<int> &color) {
if (color[start] != 0) {
return color[start] == 1;
}
color[start] = 2; // mark it as unsafe because it is on the path
for (int next : graph[start]) {
if (!dfs(graph, next, color)) {
return false;
}
}
color[start] = 1; // mark it as safe because no loop is found
return true;
}
};

  

All LeetCode Questions List 题目汇总

[LeetCode] 802. Find Eventual Safe States 找到最终的安全状态的更多相关文章

  1. [LeetCode] Find Eventual Safe States 找到最终的安全状态

    In a directed graph, we start at some node and every turn, walk along a directed edge of the graph.  ...

  2. LeetCode 802. Find Eventual Safe States

    原题链接在这里:https://leetcode.com/problems/find-eventual-safe-states/ 题目: In a directed graph, we start a ...

  3. 【LeetCode】802. Find Eventual Safe States 解题报告(Python)

    [LeetCode]802. Find Eventual Safe States 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemi ...

  4. LC 802. Find Eventual Safe States

    In a directed graph, we start at some node and every turn, walk along a directed edge of the graph.  ...

  5. 【leetcode】802. Find Eventual Safe States

    题目如下: 解题思路:本题大多数人采用DFS的方法,这里我用的是另一种方法.我的思路是建立一次初始值为空的safe数组,然后遍历graph,找到graph[i]中所有元素都在safe中的元素,把i加入 ...

  6. 802. Find Eventual Safe States

    https://leetcode.com/problems/find-eventual-safe-states/description/ class Solution { public: vector ...

  7. Java实现 LeetCode 802 找到最终的安全状态 (DFS)

    802. 找到最终的安全状态 在有向图中, 我们从某个节点和每个转向处开始, 沿着图的有向边走. 如果我们到达的节点是终点 (即它没有连出的有向边), 我们停止. 现在, 如果我们最后能走到终点,那么 ...

  8. [Swift]LeetCode802. 找到最终的安全状态 | Find Eventual Safe States

    In a directed graph, we start at some node and every turn, walk along a directed edge of the graph.  ...

  9. LeetCode 277. Find the Celebrity (找到明星)$

    Suppose you are at a party with n people (labeled from 0 to n - 1) and among them, there may exist o ...

随机推荐

  1. 《Coderxiaoban团队》团队作业5:项目需求分析改进与系统设计

    实验八 <Coderxiaoban团队>团队作业5:项目需求分析改进与系统设计 项目 内容 这个作业属于哪个课程 任课教师博客主页链接 这个作业的要求在哪里 团队作业5:项目需求分析改进与 ...

  2. python 查询文件修改python lib 库文件

    运行code import os, time import sys import re def search(path, name): for root, dirs, files in os.walk ...

  3. websocket简单样例

    服务端 var server = require('ws').Server; }); serv.on('connection',function(socket){ socket.send('hello ...

  4. 数据分析 - Numpy

    简介 Numpy是高性能科学计算和数据分析的基础包.它也是pandas等其他数据分析的工具的基础,基本所有数据分析的包都用过它.NumPy为Python带来了真正的多维数组功能,并且提供了丰富的函数库 ...

  5. Open Source Isn't A Business Model, It's A Market Strategy

    https://www.forbes.com/sites/quora/2017/09/29/open-source-isnt-a-business-model-its-a-market-strateg ...

  6. C#中ref和out的原理

    去年在CSDN上写的,现在把它搬过来. 一.引发问题 用了那么久的 ref 和 out ,你真的了解它们是如何使得实参与形参的值保持同步的吗? 二.研究前提 要研究这个问题,前提是要了解 C# 中方法 ...

  7. WebSocket 实现前后端通信的笔记

    之前在做站内信时,用到了 WebSocket ,整理了一些笔记分享如下.本文基于 SpringBoot 2.1.5,本文不涉及环境搭建. 引入依赖 在 Spring 中要使用 WebSocket 功能 ...

  8. (4)ardunio 矩阵求解官方库改造,添加逆的求解

    多此一举,原来官方库给了求逆的函数,在源码里 除此之外,还有转置矩阵,只不过样例没显示出来. //Matrix Inversion Routine // * This function inverts ...

  9. learning java FileInputStream

    public class FileInputStreamTest { public static void main(String[] args) throws IOException { var f ...

  10. Mybatis02

    1.mybatis动态sql   foreach 添加接口方法 编写BookVo类 BookMapper.xml 测试 结果 2.模糊查询 3.查询返回结果集 resultMap:适合使用返回值是自定 ...