Skip to content

Commit 908bf64

Browse files
committed
feat: add solutions to lc problem: No.0802
No.0802.Find Eventual Safe States
1 parent 63af104 commit 908bf64

File tree

7 files changed

+563
-230
lines changed

7 files changed

+563
-230
lines changed

solution/0800-0899/0802.Find Eventual Safe States/README.md

Lines changed: 245 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,22 @@
5353

5454
<!-- 这里可写通用的实现逻辑 -->
5555

56+
**方法一:拓扑排序**
57+
5658
出度为零的点是安全的,如果一个点**只能**到达安全的点,那么它同样是安全的,所以问题转换成了拓扑排序。
5759

60+
我们可以将图中所有边反向,得到一个反图,然后在反图上运行拓扑排序。
61+
62+
时间复杂度 $O(n+m)$,其中 $n$ 表示图中的点数,$m$ 表示图中的边数。
63+
64+
**方法二:DFS + 三色标记法**
65+
66+
若起始节点位于一个环内,或者能到达一个环,则该节点不是安全的。否则,该节点是安全的。
67+
68+
- 白色(用 0 表示):该节点尚未被访问;
69+
- 灰色(用 1 表示):该节点位于递归栈中,或者在某个环上;
70+
- 黑色(用 2 表示):该节点搜索完毕,是一个安全节点。
71+
5872
<!-- tabs:start -->
5973

6074
### **Python3**
@@ -64,19 +78,38 @@
6478
```python
6579
class Solution:
6680
def eventualSafeNodes(self, graph: List[List[int]]) -> List[int]:
67-
n = len(graph)
68-
outDegree = [len(vs) for vs in graph]
69-
revGraph = defaultdict(list)
70-
for u, vs in enumerate(graph):
71-
for v in vs:
72-
revGraph[v].append(u)
73-
q = deque([i for i, d in enumerate(outDegree) if d == 0])
81+
rg = defaultdict(list)
82+
indeg = [0] * len(graph)
83+
for i, vs in enumerate(graph):
84+
for j in vs:
85+
rg[j].append(i)
86+
indeg[i] = len(vs)
87+
q = deque([i for i, v in enumerate(indeg) if v == 0])
7488
while q:
75-
for u in revGraph[q.popleft()]:
76-
outDegree[u] -= 1
77-
if outDegree[u] == 0:
78-
q.append(u)
79-
return [i for i, d in enumerate(outDegree) if d == 0]
89+
i = q.popleft()
90+
for j in rg[i]:
91+
indeg[j] -= 1
92+
if indeg[j] == 0:
93+
q.append(j)
94+
return [i for i, v in enumerate(indeg) if v == 0]
95+
```
96+
97+
```python
98+
class Solution:
99+
def eventualSafeNodes(self, graph: List[List[int]]) -> List[int]:
100+
def dfs(i):
101+
if color[i]:
102+
return color[i] == 2
103+
color[i] = 1
104+
for j in graph[i]:
105+
if not dfs(j):
106+
return False
107+
color[i] = 2
108+
return True
109+
110+
n = len(graph)
111+
color = [0] * n
112+
return [i for i in range(n) if dfs(i)]
80113
```
81114

82115
### **Java**
@@ -87,39 +120,71 @@ class Solution:
87120
class Solution {
88121
public List<Integer> eventualSafeNodes(int[][] graph) {
89122
int n = graph.length;
90-
int[] outDegrees = new int[n];
91-
Queue<Integer> queue = new ArrayDeque<>();
92-
List<List<Integer>> revGraph = new ArrayList<>();
93-
for (int i = 0; i < n; i++) {
94-
revGraph.add(new ArrayList<>());
95-
}
96-
for (int u = 0; u < n; u++) {
97-
for (int v : graph[u]) {
98-
revGraph.get(v).add(u);
123+
int[] indeg = new int[n];
124+
List<Integer>[] rg = new List[n];
125+
for (int i = 0; i < n; ++i) {
126+
rg[i] = new ArrayList<>();
127+
}
128+
Deque<Integer> q = new ArrayDeque<>();
129+
for (int i = 0; i < n; ++i) {
130+
for (int j : graph[i]) {
131+
rg[j].add(i);
99132
}
100-
outDegrees[u] = graph[u].length;
101-
if (outDegrees[u] == 0) {
102-
queue.offer(u);
133+
indeg[i] = graph[i].length;
134+
if (indeg[i] == 0) {
135+
q.offer(i);
103136
}
104137
}
105-
106-
while (!queue.isEmpty()) {
107-
int v = queue.poll();
108-
for (int u : revGraph.get(v)) {
109-
if (--outDegrees[u] == 0) {
110-
queue.offer(u);
138+
while (!q.isEmpty()) {
139+
int i = q.pollFirst();
140+
for (int j : rg[i]) {
141+
if (--indeg[j] == 0) {
142+
q.offer(j);
111143
}
112144
}
113145
}
146+
List<Integer> ans = new ArrayList<>();
147+
for (int i = 0; i < n; ++i) {
148+
if (indeg[i] == 0) {
149+
ans.add(i);
150+
}
151+
}
152+
return ans;
153+
}
154+
}
155+
```
156+
157+
```java
158+
class Solution {
159+
private int[] color;
160+
private int[][] g;
114161

162+
public List<Integer> eventualSafeNodes(int[][] graph) {
163+
int n = graph.length;
164+
color = new int[n];
165+
g = graph;
115166
List<Integer> ans = new ArrayList<>();
116-
for (int i = 0; i < n; i++) {
117-
if (outDegrees[i] == 0) {
167+
for (int i = 0; i < n; ++i) {
168+
if (dfs(i)) {
118169
ans.add(i);
119170
}
120171
}
121172
return ans;
122173
}
174+
175+
private boolean dfs(int i) {
176+
if (color[i] > 0) {
177+
return color[i] == 2;
178+
}
179+
color[i] = 1;
180+
for (int j : g[i]) {
181+
if (!dfs(j)) {
182+
return false;
183+
}
184+
}
185+
color[i] = 2;
186+
return true;
187+
}
123188
}
124189
```
125190

@@ -128,34 +193,59 @@ class Solution {
128193
```go
129194
func eventualSafeNodes(graph [][]int) []int {
130195
n := len(graph)
131-
outDegree := make([]int, n)
132-
revGraph := make([][]int, n)
133-
queue := make([]int, 0)
134-
ans := make([]int, 0)
135-
136-
for u, vs := range graph {
137-
for _, v := range vs {
138-
revGraph[v] = append(revGraph[v], u)
196+
indeg := make([]int, n)
197+
rg := make([][]int, n)
198+
q := []int{}
199+
for i, vs := range graph {
200+
for _, j := range vs {
201+
rg[j] = append(rg[j], i)
139202
}
140-
outDegree[u] = len(vs)
141-
if outDegree[u] == 0 {
142-
queue = append(queue, u)
203+
indeg[i] = len(vs)
204+
if indeg[i] == 0 {
205+
q = append(q, i)
143206
}
144207
}
145-
146-
for len(queue) > 0 {
147-
v := queue[0]
148-
queue = queue[1:]
149-
for _, u := range revGraph[v] {
150-
outDegree[u]--
151-
if outDegree[u] == 0 {
152-
queue = append(queue, u)
208+
for len(q) > 0 {
209+
i := q[0]
210+
q = q[1:]
211+
for _, j := range rg[i] {
212+
indeg[j]--
213+
if indeg[j] == 0 {
214+
q = append(q, j)
153215
}
154216
}
155217
}
218+
ans := []int{}
219+
for i, v := range indeg {
220+
if v == 0 {
221+
ans = append(ans, i)
222+
}
223+
}
224+
return ans
225+
}
226+
```
156227

157-
for i, d := range outDegree {
158-
if d == 0 {
228+
```go
229+
func eventualSafeNodes(graph [][]int) []int {
230+
n := len(graph)
231+
color := make([]int, n)
232+
var dfs func(int) bool
233+
dfs = func(i int) bool {
234+
if color[i] > 0 {
235+
return color[i] == 2
236+
}
237+
color[i] = 1
238+
for _, j := range graph[i] {
239+
if !dfs(j) {
240+
return false
241+
}
242+
}
243+
color[i] = 2
244+
return true
245+
}
246+
ans := []int{}
247+
for i := range graph {
248+
if dfs(i) {
159249
ans = append(ans, i)
160250
}
161251
}
@@ -168,36 +258,120 @@ func eventualSafeNodes(graph [][]int) []int {
168258
```cpp
169259
class Solution {
170260
public:
171-
vector<int> eventualSafeNodes(vector<vector<int>> &graph) {
261+
vector<int> eventualSafeNodes(vector<vector<int>>& graph) {
172262
int n = graph.size();
173-
vector<vector<int>> revGraph(n);
174-
vector<int> outDegree(n);
263+
vector<int> indeg(n);
264+
vector<vector<int>> rg(n);
265+
queue<int> q;
175266
for (int i = 0; i < n; ++i)
176267
{
177-
outDegree[i] += graph[i].size();
178-
for (int j : graph[i])
179-
revGraph[j].push_back(i);
268+
for (int j : graph[i]) rg[j].push_back(i);
269+
indeg[i] = graph[i].size();
270+
if (indeg[i] == 0) q.push(i);
180271
}
181-
queue<int> q;
182-
for (int i = 0; i < n; ++i)
183-
if (outDegree[i] == 0)
184-
q.push(i);
185272
while (!q.empty())
186273
{
187274
int i = q.front();
188275
q.pop();
189-
for (int j : revGraph[i])
190-
{
191-
if (--outDegree[j] == 0)
192-
q.push(j);
193-
}
276+
for (int j : rg[i]) if (--indeg[j] == 0) q.push(j);
194277
}
195278
vector<int> ans;
196-
for (int i = 0; i < n; ++i)
197-
if (outDegree[i] == 0)
198-
ans.push_back(i);
279+
for (int i = 0; i < n; ++i) if (indeg[i] == 0) ans.push_back(i);
280+
return ans;
281+
}
282+
};
283+
```
284+
285+
```cpp
286+
class Solution {
287+
public:
288+
vector<int> color;
289+
290+
vector<int> eventualSafeNodes(vector<vector<int>>& graph) {
291+
int n = graph.size();
292+
color.assign(n, 0);
293+
vector<int> ans;
294+
for (int i = 0; i < n; ++i) if (dfs(i, graph)) ans.push_back(i);
199295
return ans;
200296
}
297+
298+
bool dfs(int i, vector<vector<int>>& g) {
299+
if (color[i]) return color[i] == 2;
300+
color[i] = 1;
301+
for (int j : g[i]) if (!dfs(j, g)) return false;
302+
color[i] = 2;
303+
return true;
304+
}
305+
};
306+
```
307+
308+
### **JavaScript**
309+
310+
```js
311+
/**
312+
* @param {number[][]} graph
313+
* @return {number[]}
314+
*/
315+
var eventualSafeNodes = function (graph) {
316+
const n = graph.length;
317+
const rg = new Array(n).fill(0).map(() => new Array());
318+
const indeg = new Array(n).fill(0);
319+
const q = [];
320+
for (let i = 0; i < n; ++i) {
321+
for (let j of graph[i]) {
322+
rg[j].push(i);
323+
}
324+
indeg[i] = graph[i].length;
325+
if (indeg[i] == 0) {
326+
q.push(i);
327+
}
328+
}
329+
while (q.length) {
330+
const i = q.shift();
331+
for (let j of rg[i]) {
332+
if (--indeg[j] == 0) {
333+
q.push(j);
334+
}
335+
}
336+
}
337+
let ans = [];
338+
for (let i = 0; i < n; ++i) {
339+
if (indeg[i] == 0) {
340+
ans.push(i);
341+
}
342+
}
343+
return ans;
344+
};
345+
```
346+
347+
```js
348+
/**
349+
* @param {number[][]} graph
350+
* @return {number[]}
351+
*/
352+
var eventualSafeNodes = function (graph) {
353+
const n = graph.length;
354+
const color = new Array(n).fill(0);
355+
function dfs(i) {
356+
if (color[i]) {
357+
return color[i] == 2;
358+
}
359+
color[i] = 1;
360+
for (const j of graph[i]) {
361+
if (!dfs(j)) {
362+
return false;
363+
}
364+
}
365+
color[i] = 2;
366+
return true;
367+
}
368+
let ans = [];
369+
for (let i = 0; i < n; ++i) {
370+
if (dfs(i)) {
371+
ans.push(i);
372+
}
373+
}
374+
return ans;
201375
};
202376
```
203377

0 commit comments

Comments
 (0)