Skip to content

Commit dd95606

Browse files
authored
feat: add solutions to lc problem: No.1059 (#4874)
1 parent de3e3bd commit dd95606

File tree

7 files changed

+354
-201
lines changed

7 files changed

+354
-201
lines changed

solution/1000-1099/1059.All Paths from Source Lead to Destination/README.md

Lines changed: 121 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -78,23 +78,25 @@ tags:
7878

7979
<!-- solution:start -->
8080

81-
### 方法一:记忆化搜索
81+
### 方法一:DFS
8282

83-
建图,然后从 `source` 出发,进行深度优先搜索
83+
我们用一个状态数组 $\textit{state}$ 来记录每个节点的状态,其中
8484

85-
如果遇到了 `destination`,判断此时是否还有出边,如果有出边,返回 `false`,否则返回 `true`
85+
- 状态 0 表示该节点未被访问过;
86+
- 状态 1 表示该节点正在被访问;
87+
- 状态 2 表示该节点已经被访问过且可以通向终点。
8688

87-
如果遇到了环(此前访问过),或者遇到了没有出边的节点,直接返回 `false`
89+
我们首先将图构建为邻接表的形式,然后从起点出发进行深度优先搜索(DFS)。在 DFS 过程中:
8890

89-
否则,我们把当前节点标记为已访问,然后对当前节点的所有出边进行深度优先搜索,只要有一条路径无法可以到达 `destination`,就返回 `false`,否则返回 `true`
91+
- 如果当前节点的状态为 1,说明我们遇到了一个环,直接返回 $\text{false}$;
92+
- 如果当前节点的状态为 2,说明该节点已经被访问过且可以通向终点,直接返回 $\text{true}$;
93+
- 如果当前节点没有出边,则检查该节点是否为终点,如果是则返回 $\text{true}$,否则返回 $\text{false}$;
94+
- 否则,将当前节点的状态设为 1,递归访问所有相邻节点;
95+
- 如果所有相邻节点都能通向终点,则将当前节点的状态设为 2 并返回 $\text{true}$,否则返回 $\text{false}$。
9096

91-
过程中我们用一个数组 $f$ 记录每个节点的状态,每个 $f[i]$ 的值有三种,分别表示:
97+
答案为 $\text{dfs}(\text{source})$ 的结果。
9298

93-
- 对于 $f[i] = 0$,表示节点 $i$ 未被访问;
94-
- 对于 $f[i] = 1$,表示节点 $i$ 已被访问,且可以到达 `destination`
95-
- 对于 $f[i] = 2$,表示节点 $i$ 已被访问,但无法到达 `destination`
96-
97-
时间复杂度 $O(n)$。其中 $n$ 为节点数。
99+
时间复杂度 $O(n + m)$,其中 $n$ 和 $m$ 分别为节点数和边数。空间复杂度 $O(n + m)$,用于存储图的邻接表和状态数组。
98100

99101
<!-- tabs:start -->
100102

@@ -105,22 +107,26 @@ class Solution:
105107
def leadsToDestination(
106108
self, n: int, edges: List[List[int]], source: int, destination: int
107109
) -> bool:
108-
@cache
109-
def dfs(i):
110-
if i == destination:
111-
return not g[i]
112-
if i in vis or not g[i]:
113-
return False
114-
vis.add(i)
110+
def dfs(i: int) -> bool:
111+
if st[i]:
112+
return st[i] == 2
113+
if not g[i]:
114+
return i == destination
115+
116+
st[i] = 1
115117
for j in g[i]:
116118
if not dfs(j):
117119
return False
120+
st[i] = 2
118121
return True
119122

120-
g = defaultdict(list)
123+
g = [[] for _ in range(n)]
121124
for a, b in edges:
122125
g[a].append(b)
123-
vis = set()
126+
if g[destination]:
127+
return False
128+
129+
st = [0] * n
124130
return dfs(source)
125131
```
126132

@@ -129,40 +135,37 @@ class Solution:
129135
```java
130136
class Solution {
131137
private List<Integer>[] g;
132-
private int[] f;
133-
private boolean[] vis;
134-
private int k;
138+
private int[] st;
139+
private int destination;
135140

136141
public boolean leadsToDestination(int n, int[][] edges, int source, int destination) {
137-
vis = new boolean[n];
142+
this.destination = destination;
138143
g = new List[n];
139-
k = destination;
140-
f = new int[n];
141-
Arrays.setAll(g, key -> new ArrayList<>());
142-
for (var e : edges) {
144+
Arrays.setAll(g, k -> new ArrayList<>());
145+
for (int[] e : edges) {
143146
g[e[0]].add(e[1]);
144147
}
148+
if (!g[destination].isEmpty()) {
149+
return false;
150+
}
151+
st = new int[n];
145152
return dfs(source);
146153
}
147154

148155
private boolean dfs(int i) {
149-
if (i == k) {
150-
return g[i].isEmpty();
156+
if (st[i] != 0) {
157+
return st[i] == 2;
151158
}
152-
if (f[i] != 0) {
153-
return f[i] == 1;
159+
if (g[i].isEmpty()) {
160+
return i == destination;
154161
}
155-
if (vis[i] || g[i].isEmpty()) {
156-
return false;
157-
}
158-
vis[i] = true;
162+
st[i] = 1;
159163
for (int j : g[i]) {
160164
if (!dfs(j)) {
161-
f[i] = -1;
162165
return false;
163166
}
164167
}
165-
f[i] = 1;
168+
st[i] = 2;
166169
return true;
167170
}
168171
}
@@ -173,34 +176,38 @@ class Solution {
173176
```cpp
174177
class Solution {
175178
public:
179+
vector<vector<int>> g;
180+
vector<int> st;
181+
int destination;
182+
176183
bool leadsToDestination(int n, vector<vector<int>>& edges, int source, int destination) {
177-
vector<bool> vis(n);
178-
vector<vector<int>> g(n);
179-
vector<int> f(n);
184+
this->destination = destination;
185+
g.assign(n, {});
180186
for (auto& e : edges) {
181187
g[e[0]].push_back(e[1]);
182188
}
183-
function<bool(int)> dfs = [&](int i) {
184-
if (i == destination) {
185-
return g[i].empty();
186-
}
187-
if (f[i]) {
188-
return f[i] == 1;
189-
}
190-
if (vis[i] || g[i].empty()) {
189+
if (!g[destination].empty()) {
190+
return false;
191+
}
192+
st.assign(n, 0);
193+
return dfs(source);
194+
}
195+
196+
bool dfs(int i) {
197+
if (st[i] != 0) {
198+
return st[i] == 2;
199+
}
200+
if (g[i].empty()) {
201+
return i == destination;
202+
}
203+
st[i] = 1;
204+
for (int j : g[i]) {
205+
if (!dfs(j)) {
191206
return false;
192207
}
193-
vis[i] = true;
194-
for (int j : g[i]) {
195-
if (!dfs(j)) {
196-
f[i] = -1;
197-
return false;
198-
}
199-
}
200-
f[i] = 1;
201-
return true;
202-
};
203-
return dfs(source);
208+
}
209+
st[i] = 2;
210+
return true;
204211
}
205212
};
206213
```
@@ -209,37 +216,78 @@ public:
209216

210217
```go
211218
func leadsToDestination(n int, edges [][]int, source int, destination int) bool {
212-
vis := make([]bool, n)
213219
g := make([][]int, n)
214-
f := make([]int, n)
215220
for _, e := range edges {
216221
g[e[0]] = append(g[e[0]], e[1])
217222
}
218-
var dfs func(int) bool
223+
if len(g[destination]) > 0 {
224+
return false
225+
}
226+
227+
st := make([]int, n)
228+
229+
var dfs func(i int) bool
219230
dfs = func(i int) bool {
220-
if i == destination {
221-
return len(g[i]) == 0
222-
}
223-
if f[i] != 0 {
224-
return f[i] == 1
231+
if st[i] != 0 {
232+
return st[i] == 2
225233
}
226-
if vis[i] || len(g[i]) == 0 {
227-
return false
234+
if len(g[i]) == 0 {
235+
return i == destination
228236
}
229-
vis[i] = true
237+
st[i] = 1
230238
for _, j := range g[i] {
231239
if !dfs(j) {
232-
f[i] = -1
233240
return false
234241
}
235242
}
236-
f[i] = 1
243+
st[i] = 2
237244
return true
238245
}
246+
239247
return dfs(source)
240248
}
241249
```
242250

251+
#### TypeScript
252+
253+
```ts
254+
function leadsToDestination(
255+
n: number,
256+
edges: number[][],
257+
source: number,
258+
destination: number,
259+
): boolean {
260+
const g: number[][] = Array.from({ length: n }, () => []);
261+
for (const [a, b] of edges) {
262+
g[a].push(b);
263+
}
264+
if (g[destination].length > 0) {
265+
return false;
266+
}
267+
268+
const st: number[] = Array(n).fill(0);
269+
270+
const dfs = (i: number): boolean => {
271+
if (st[i] !== 0) {
272+
return st[i] === 2;
273+
}
274+
if (g[i].length === 0) {
275+
return i === destination;
276+
}
277+
st[i] = 1;
278+
for (const j of g[i]) {
279+
if (!dfs(j)) {
280+
return false;
281+
}
282+
}
283+
st[i] = 2;
284+
return true;
285+
};
286+
287+
return dfs(source);
288+
}
289+
```
290+
243291
<!-- tabs:end -->
244292

245293
<!-- solution:end -->

0 commit comments

Comments
 (0)