[LeetCode] 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. 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:
graphwill have length at most10000.- 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 找到最终的安全状态的更多相关文章
- [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. ...
- LeetCode 802. Find Eventual Safe States
原题链接在这里:https://leetcode.com/problems/find-eventual-safe-states/ 题目: In a directed graph, we start a ...
- 【LeetCode】802. Find Eventual Safe States 解题报告(Python)
[LeetCode]802. Find Eventual Safe States 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemi ...
- 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. ...
- 【leetcode】802. Find Eventual Safe States
题目如下: 解题思路:本题大多数人采用DFS的方法,这里我用的是另一种方法.我的思路是建立一次初始值为空的safe数组,然后遍历graph,找到graph[i]中所有元素都在safe中的元素,把i加入 ...
- 802. Find Eventual Safe States
https://leetcode.com/problems/find-eventual-safe-states/description/ class Solution { public: vector ...
- Java实现 LeetCode 802 找到最终的安全状态 (DFS)
802. 找到最终的安全状态 在有向图中, 我们从某个节点和每个转向处开始, 沿着图的有向边走. 如果我们到达的节点是终点 (即它没有连出的有向边), 我们停止. 现在, 如果我们最后能走到终点,那么 ...
- [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. ...
- 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 ...
随机推荐
- appium+python自动化64-使用Uiautomator2执行driver.keyevent()方法报错解决
前言 未加'automationName': 'Uiautomator2'参数使用Uiautomator可以正常使用driver.keyevent()方法,使用Uiautomator2时driver. ...
- SQL之CASE WHEN用法详解(转)
当我们需要从数据源上 直接判断数据显示代表的含义的时候 ,就可以在SQL语句中使用 Case When这个函数了. Case具有两种格式.简单Case函数和Case搜索函数. 第一种 格式 : 简单C ...
- spring的声明式事务和编程式事务
事务管理对于企业应用来说是至关重要的,当出现异常情况时,它可以保证数据的一致性. Spring事务管理的两种方式 1.编程式事务 使用Transaction Ttempleate或者直接使用底层的Pl ...
- js里调用函数时,函数名带括号与不带括号的区别
function test(){ return 1;}var a=test;console.log(a);//输出[Function: test]var b=test();console.log(b) ...
- 最小圆覆盖(洛谷 P1742 增量法)
题意:给定N个点,求最小圆覆盖的圆心喝半径.保留10位小数点. N<1e5: 思路:因为精度要求较高,而且N比较大,所以三分套三分的复杂度耶比较高,而且容易出错. 然是写下增量法吧. 伪代码加深 ...
- vue中点击不同的em添加class去除兄弟级class
vue中使用v-for循环li 怎么点击每个li中的em给添加class删除兄弟元素 <html lang="en"> <head> <meta ch ...
- LeetCode 787. Cheapest Flights Within K Stops
原题链接在这里:https://leetcode.com/problems/cheapest-flights-within-k-stops/ 题目: There are n cities connec ...
- edgedb-js 来自官方的js 驱动
目前对于edgedb 主要还是来自官方的python驱动,目前js 版本的已经快发布了,代码在github 可以看到了 同时官方文档也提供了一个关于edgedb 内部的协议说明,结合js 驱动以及文档 ...
- Mybatis 面试题
题目: 什么是Mybatis? Mybatis27题 Mybaits的优点 Mybatis27题 MyBatis框架的缺点 Mybatis27题 MyBatis框架适用场合Mybatis27题 My ...
- Sql注入基本思路
Sql注入基本思路 利用mysql自己动手 登录 使用show databases;查看数据库,sql注入主要用到的是information_schema这个库(mysql中大小写不敏感) infor ...