赞
踩
https://leetcode.com/problems/find-eventual-safe-states/
给定一个有向图,如果从一个点出发走若干步后总会走到一个出度为 0 0 0的点,则称其为eventual safe。要求返回该图中所有的eventual safe的点。
题目的本质是要求把能走到某个环上的点都去掉不返回,而只返回那些走不到环上的点。一个点能否走到环上,当且仅当其邻居能否走到环上,这是一个递归的问题。我们可以对每个点进行染色, 0 0 0代表还没访问,可以进行访问;染 1 1 1代表本次DFS正在访问,染 2 2 2代表不能走到环上。同时我们让DFS返回是否发现了环,发现了环(表示当前顶点不是eventual safe的)则返回false,否则返回true。开始对每个点进行DFS,如果这个点之前已经染了色了,那说明之前DFS的时候已经判断好了其是否能走到环上,视情况加入最终结果即可;如果没染色(意思是标记为 0 0 0),那就对其进行访问,先将其标记为 1 1 1,然后开始访问其邻居,如果邻居为 2 2 2,说明该邻居走不到环上,略过;如果邻居为 1 1 1,说明产生了环,返回false;如果对邻居进行DFS发现了环,那也说明当前顶点不是eventual safe的,返回false。对其邻居全遍历完后如果都没有返回false,说明当前顶点是eventual safe的,则将其染为 2 2 2,同时返回true。只需要将所有染为 2 2 2的顶点加入最终结果即可,事实上,最后染为 1 1 1的点就是能走到环上的点。代码如下:
import java.util.ArrayList; import java.util.List; public class Solution { public List<Integer> eventualSafeNodes(int[][] graph) { List<Integer> res = new ArrayList<>(); // 判空 if (graph == null) { return res; } int[] color = new int[graph.length]; for (int i = 0; i < graph.length; ++i) { if (dfs(i, color, graph)) { res.add(i); } } return res; } // 从node开始DFS,返回node是否是eventual safe的 public boolean dfs(int node, int[] color, int[][] graph) { // 如果之前访问过,就返回其是否eventual safe if (color[node] > 0) { return color[node] == 2; } // 标记其为正在访问 color[node] = 1; // 开始递归遍历其邻居 for (int next: graph[node]) { // 如果已经知道next不会走到环了,就不必访问了,略过 if (color[next] == 2) { continue; } // 如果next在当前DFS访问过,说明产生了环,返回false; // 如果next未访问过则对其进行访问,如果发现了环返回false if (color[next] == 1 || !dfs(next, color, graph)) { return false; } } // 如果之前都没发现环,则标记为2,返回true color[node] = 2; return true; } }
时间复杂度 O ( V + E ) O(V+E) O(V+E),空间 O ( V ) O(V) O(V)。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。