Skip to content

Commit fa17fec

Browse files
authored
feat: add solutions to lcci problem: No.04.01 (doocs#2534)
1 parent de0b673 commit fa17fec

File tree

12 files changed

+515
-277
lines changed

12 files changed

+515
-277
lines changed

lcci/04.01.Route Between Nodes/README.md

Lines changed: 178 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -31,52 +31,66 @@
3131

3232
### 方法一:DFS
3333

34+
我们先根据给定的图构建一个邻接表 $g$,其中 $g[i]$ 表示节点 $i$ 的所有邻居节点,用一个哈希表或数组 $vis$ 记录访问过的节点,然后从节点 $start$ 开始深度优先搜索,如果搜索到节点 $target$,则返回 `true`,否则返回 `false`
35+
36+
深度优先搜索的过程如下:
37+
38+
1. 如果当前节点 $i$ 等于目标节点 $target$,返回 `true`
39+
2. 如果当前节点 $i$ 已经访问过,返回 `false`
40+
3. 否则,将当前节点 $i$ 标记为已访问,然后遍历节点 $i$ 的所有邻居节点 $j$,递归地搜索节点 $j$。
41+
42+
时间复杂度 $(n + m)$,空间复杂度 $O(n + m)$。其中 $n$ 和 $m$ 分别是节点数量和边数量。
43+
3444
<!-- tabs:start -->
3545

3646
```python
3747
class Solution:
3848
def findWhetherExistsPath(
3949
self, n: int, graph: List[List[int]], start: int, target: int
4050
) -> bool:
41-
def dfs(u):
42-
if u == target:
51+
def dfs(i: int):
52+
if i == target:
4353
return True
44-
for v in g[u]:
45-
if v not in vis:
46-
vis.add(v)
47-
if dfs(v):
48-
return True
49-
return False
50-
51-
g = defaultdict(list)
52-
for u, v in graph:
53-
g[u].append(v)
54-
vis = {start}
54+
if i in vis:
55+
return False
56+
vis.add(i)
57+
return any(dfs(j) for j in g[i])
58+
59+
g = [[] for _ in range(n)]
60+
for a, b in graph:
61+
g[a].append(b)
62+
vis = set()
5563
return dfs(start)
5664
```
5765

5866
```java
5967
class Solution {
68+
private List<Integer>[] g;
69+
private boolean[] vis;
70+
private int target;
71+
6072
public boolean findWhetherExistsPath(int n, int[][] graph, int start, int target) {
61-
Map<Integer, List<Integer>> g = new HashMap<>();
73+
vis = new boolean[n];
74+
g = new List[n];
75+
this.target = target;
76+
Arrays.setAll(g, k -> new ArrayList<>());
6277
for (int[] e : graph) {
63-
g.computeIfAbsent(e[0], k -> new ArrayList<>()).add(e[1]);
78+
g[e[0]].add(e[1]);
6479
}
65-
Set<Integer> vis = new HashSet<>();
66-
vis.add(start);
67-
return dfs(start, target, g, vis);
80+
return dfs(start);
6881
}
6982

70-
private boolean dfs(int u, int target, Map<Integer, List<Integer>> g, Set<Integer> vis) {
71-
if (u == target) {
83+
private boolean dfs(int i) {
84+
if (i == target) {
7285
return true;
7386
}
74-
for (int v : g.getOrDefault(u, Collections.emptyList())) {
75-
if (!vis.contains(v)) {
76-
vis.add(v);
77-
if (dfs(v, target, g, vis)) {
78-
return true;
79-
}
87+
if (vis[i]) {
88+
return false;
89+
}
90+
vis[i] = true;
91+
for (int j : g[i]) {
92+
if (dfs(j)) {
93+
return true;
8094
}
8195
}
8296
return false;
@@ -88,44 +102,50 @@ class Solution {
88102
class Solution {
89103
public:
90104
bool findWhetherExistsPath(int n, vector<vector<int>>& graph, int start, int target) {
91-
unordered_map<int, vector<int>> g;
92-
for (auto& e : graph) g[e[0]].push_back(e[1]);
93-
unordered_set<int> vis{{start}};
94-
return dfs(start, target, g, vis);
95-
}
96-
97-
bool dfs(int u, int& target, unordered_map<int, vector<int>>& g, unordered_set<int>& vis) {
98-
if (u == target) return true;
99-
for (int& v : g[u]) {
100-
if (!vis.count(v)) {
101-
vis.insert(v);
102-
if (dfs(v, target, g, vis)) return true;
103-
}
105+
vector<int> g[n];
106+
vector<bool> vis(n);
107+
for (auto& e : graph) {
108+
g[e[0]].push_back(e[1]);
104109
}
105-
return false;
110+
function<bool(int)> dfs = [&](int i) {
111+
if (i == target) {
112+
return true;
113+
}
114+
if (vis[i]) {
115+
return false;
116+
}
117+
vis[i] = true;
118+
for (int j : g[i]) {
119+
if (dfs(j)) {
120+
return true;
121+
}
122+
}
123+
return false;
124+
};
125+
return dfs(start);
106126
}
107127
};
108128
```
109129
110130
```go
111131
func findWhetherExistsPath(n int, graph [][]int, start int, target int) bool {
112-
g := map[int][]int{}
132+
g := make([][]int, n)
133+
vis := make([]bool, n)
113134
for _, e := range graph {
114-
u, v := e[0], e[1]
115-
g[u] = append(g[u], v)
135+
g[e[0]] = append(g[e[0]], e[1])
116136
}
117-
vis := map[int]bool{start: true}
118137
var dfs func(int) bool
119-
dfs = func(u int) bool {
120-
if u == target {
138+
dfs = func(i int) bool {
139+
if i == target {
121140
return true
122141
}
123-
for _, v := range g[u] {
124-
if !vis[v] {
125-
vis[v] = true
126-
if dfs(v) {
127-
return true
128-
}
142+
if vis[i] {
143+
return false
144+
}
145+
vis[i] = true
146+
for _, j := range g[i] {
147+
if dfs(j) {
148+
return true
129149
}
130150
}
131151
return false
@@ -134,53 +154,84 @@ func findWhetherExistsPath(n int, graph [][]int, start int, target int) bool {
134154
}
135155
```
136156

157+
```ts
158+
function findWhetherExistsPath(
159+
n: number,
160+
graph: number[][],
161+
start: number,
162+
target: number,
163+
): boolean {
164+
const g: number[][] = Array.from({ length: n }, () => []);
165+
const vis: boolean[] = Array.from({ length: n }, () => false);
166+
for (const [a, b] of graph) {
167+
g[a].push(b);
168+
}
169+
const dfs = (i: number): boolean => {
170+
if (i === target) {
171+
return true;
172+
}
173+
if (vis[i]) {
174+
return false;
175+
}
176+
vis[i] = true;
177+
return g[i].some(dfs);
178+
};
179+
return dfs(start);
180+
}
181+
```
182+
137183
<!-- tabs:end -->
138184

139185
### 方法二:BFS
140186

187+
与方法一类似,我们先根据给定的图构建一个邻接表 $g$,其中 $g[i]$ 表示节点 $i$ 的所有邻居节点,用一个哈希表或数组 $vis$ 记录访问过的节点,然后从节点 $start$ 开始广度优先搜索,如果搜索到节点 $target$,则返回 `true`,否则返回 `false`
188+
189+
时间复杂度 $(n + m)$,空间复杂度 $O(n + m)$。其中 $n$ 和 $m$ 分别是节点数量和边数量。
190+
141191
<!-- tabs:start -->
142192

143193
```python
144194
class Solution:
145195
def findWhetherExistsPath(
146196
self, n: int, graph: List[List[int]], start: int, target: int
147197
) -> bool:
148-
g = defaultdict(list)
149-
for u, v in graph:
150-
g[u].append(v)
151-
q = deque([start])
198+
g = [[] for _ in range(n)]
199+
for a, b in graph:
200+
g[a].append(b)
152201
vis = {start}
202+
q = deque([start])
153203
while q:
154-
u = q.popleft()
155-
if u == target:
204+
i = q.popleft()
205+
if i == target:
156206
return True
157-
for v in g[u]:
158-
if v not in vis:
159-
vis.add(v)
160-
q.append(v)
207+
for j in g[i]:
208+
if j not in vis:
209+
vis.add(j)
210+
q.append(j)
161211
return False
162212
```
163213

164214
```java
165215
class Solution {
166216
public boolean findWhetherExistsPath(int n, int[][] graph, int start, int target) {
167-
Map<Integer, List<Integer>> g = new HashMap<>();
217+
List<Integer>[] g = new List[n];
218+
Arrays.setAll(g, k -> new ArrayList<>());
219+
boolean[] vis = new boolean[n];
168220
for (int[] e : graph) {
169-
g.computeIfAbsent(e[0], k -> new ArrayList<>()).add(e[1]);
221+
g[e[0]].add(e[1]);
170222
}
171223
Deque<Integer> q = new ArrayDeque<>();
172224
q.offer(start);
173-
Set<Integer> vis = new HashSet<>();
174-
vis.add(start);
225+
vis[start] = true;
175226
while (!q.isEmpty()) {
176-
int u = q.poll();
177-
if (u == target) {
227+
int i = q.poll();
228+
if (i == target) {
178229
return true;
179230
}
180-
for (int v : g.getOrDefault(u, Collections.emptyList())) {
181-
if (!vis.contains(v)) {
182-
vis.add(v);
183-
q.offer(v);
231+
for (int j : g[i]) {
232+
if (!vis[j]) {
233+
q.offer(j);
234+
vis[j] = true;
184235
}
185236
}
186237
}
@@ -193,18 +244,23 @@ class Solution {
193244
class Solution {
194245
public:
195246
bool findWhetherExistsPath(int n, vector<vector<int>>& graph, int start, int target) {
196-
unordered_map<int, vector<int>> g;
197-
for (auto& e : graph) g[e[0]].push_back(e[1]);
247+
vector<int> g[n];
248+
vector<bool> vis(n);
249+
for (auto& e : graph) {
250+
g[e[0]].push_back(e[1]);
251+
}
198252
queue<int> q{{start}};
199-
unordered_set<int> vis{{start}};
253+
vis[start] = true;
200254
while (!q.empty()) {
201-
int u = q.front();
202-
if (u == target) return true;
255+
int i = q.front();
203256
q.pop();
204-
for (int v : g[u]) {
205-
if (!vis.count(v)) {
206-
vis.insert(v);
207-
q.push(v);
257+
if (i == target) {
258+
return true;
259+
}
260+
for (int j : g[i]) {
261+
if (!vis[j]) {
262+
q.push(j);
263+
vis[j] = true;
208264
}
209265
}
210266
}
@@ -215,30 +271,60 @@ public:
215271
216272
```go
217273
func findWhetherExistsPath(n int, graph [][]int, start int, target int) bool {
218-
g := map[int][]int{}
274+
g := make([][]int, n)
275+
vis := make([]bool, n)
219276
for _, e := range graph {
220-
u, v := e[0], e[1]
221-
g[u] = append(g[u], v)
277+
g[e[0]] = append(g[e[0]], e[1])
222278
}
223279
q := []int{start}
224-
vis := map[int]bool{start: true}
280+
vis[start] = true
225281
for len(q) > 0 {
226-
u := q[0]
227-
if u == target {
282+
i := q[0]
283+
q = q[1:]
284+
if i == target {
228285
return true
229286
}
230-
q = q[1:]
231-
for _, v := range g[u] {
232-
if !vis[v] {
233-
vis[v] = true
234-
q = append(q, v)
287+
for _, j := range g[i] {
288+
if !vis[j] {
289+
vis[j] = true
290+
q = append(q, j)
235291
}
236292
}
237293
}
238294
return false
239295
}
240296
```
241297

298+
```ts
299+
function findWhetherExistsPath(
300+
n: number,
301+
graph: number[][],
302+
start: number,
303+
target: number,
304+
): boolean {
305+
const g: number[][] = Array.from({ length: n }, () => []);
306+
const vis: boolean[] = Array.from({ length: n }, () => false);
307+
for (const [a, b] of graph) {
308+
g[a].push(b);
309+
}
310+
const q: number[] = [start];
311+
vis[start] = true;
312+
while (q.length > 0) {
313+
const i = q.pop()!;
314+
if (i === target) {
315+
return true;
316+
}
317+
for (const j of g[i]) {
318+
if (!vis[j]) {
319+
vis[j] = true;
320+
q.push(j);
321+
}
322+
}
323+
}
324+
return false;
325+
}
326+
```
327+
242328
<!-- tabs:end -->
243329

244330
<!-- end -->

0 commit comments

Comments
 (0)