Skip to content

Commit d517778

Browse files
committed
Add: Add 2025/1/24
1 parent 37fbb18 commit d517778

File tree

2 files changed

+130
-0
lines changed

2 files changed

+130
-0
lines changed

802-Find Eventual Safe States/Note.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# 802. Find Eventual Safe States
2+
3+
There is a directed graph of `n` nodes with each node labeled from `0` to `n - 1`.
4+
The graph is represented by a 0-indexed 2D integer array `graph` where
5+
`graph[i]` is an integer array of nodes adjacent to node `i`,
6+
meaning there is an edge from node `i` to each node in `graph[i]`.
7+
8+
A node is a terminal node if there are no outgoing edges.
9+
A node is a safe node if every possible path starting from that node leads to a terminal node (or another safe node).
10+
11+
Return an array containing all the safe nodes of the graph. The answer should be sorted in ascending order.
12+
13+
## 基礎思路
14+
對於每個 Node 做 DFS,為了減少重複運算,我們用一個 visited 陣列來記錄每個 Node 的狀態,分為三種狀態:
15+
16+
- 0: 未訪問
17+
- 1: 訪問中繼點
18+
- 2: 安全
19+
20+
我們只對未訪問的 Node 做 DFS,如果 DFS 過程中遇到訪問中繼點,則表示有環,此 Node 不安全,直接回傳 false,並把該 Node 設為不安全。
21+
如果 DFS 過程中沒有遇到不安全的 Node,則會把該 Node 設為安全,表示到達此解點的路徑都是安全的。
22+
23+
## 解題步驟
24+
25+
### Step 1: 紀錄 Graph 長度
26+
27+
```typescript
28+
const n = graph.length;
29+
```
30+
31+
### Step 2: 初始化 visited 陣列
32+
33+
```typescript
34+
// 0: 未訪問, 1: 訪問中繼點, 2: 安全
35+
const visited = new Array(n).fill(0);
36+
```
37+
38+
### Step 3: 定義 DFS 函數
39+
40+
```typescript
41+
function dfs(node: number): boolean {
42+
// 如果該 Node 已經訪問過,則直接回傳該 Node 是否是安全
43+
if (visited[node] > 0) {
44+
return visited[node] === 2;
45+
}
46+
47+
// 設定該 Node 為訪問中繼點
48+
visited[node] = 1;
49+
50+
// 持續檢查下一個 Node 是否安全
51+
// Note: 如果陣列是空的,則不會進入迴圈,會直接跳過 for 迴圈
52+
for (const next of graph[node]) {
53+
// 如果下一個 Node 不安全,則設定當前 Node 為不安全
54+
if (!dfs(next)) {
55+
return false;
56+
}
57+
}
58+
59+
// 設定該 Node 為安全
60+
visited[node] = 2;
61+
return true;
62+
}
63+
```
64+
65+
### Step 4: 開始 DFS
66+
67+
```typescript
68+
// 紀錄結果
69+
const result: number[] = [];
70+
71+
// 檢查每個 Node 是否安全
72+
for (let i = 0; i < n; i++) {
73+
// 如果 Node 是安全的,則加入結果中
74+
if (dfs(i)) {
75+
result.push(i);
76+
}
77+
}
78+
```
79+
80+
## 時間複雜度
81+
- 每個 Node 與 Edge 都只會被訪問一次,所以時間複雜度為 $O(V + E)$
82+
83+
> $O(V + E)$
84+
85+
## 空間複雜度
86+
- 額外使用了 visited 陣列,所以空間複雜度為 $O(V)$
87+
88+
> $O(V)$
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
function eventualSafeNodes(graph: number[][]): number[] {
2+
const n = graph.length;
3+
4+
// 0: unvisited, 1: visiting, 2: safe
5+
const visited = new Array(n).fill(0);
6+
7+
function dfs(node: number): boolean {
8+
// If the node is visited, return the safety of the node
9+
if (visited[node] > 0) {
10+
return visited[node] === 2;
11+
}
12+
13+
// Mark the node as visiting
14+
visited[node] = 1;
15+
16+
// Check the safety of the next nodes
17+
// Note: While the array is empty, the for loop will not run
18+
for (const next of graph[node]) {
19+
// If the next node is not safe, then the current node is not safe
20+
if (!dfs(next)) {
21+
return false;
22+
}
23+
}
24+
25+
// Mark the node as safe
26+
visited[node] = 2;
27+
return true;
28+
}
29+
30+
31+
// Now traverse all the nodes and check if they are safe
32+
const result: number[] = [];
33+
34+
for (let i = 0; i < n; i++) {
35+
// If the node is safe, then add it to the result
36+
if (dfs(i)) {
37+
result.push(i);
38+
}
39+
}
40+
41+
return result;
42+
}

0 commit comments

Comments
 (0)