Skip to content

Commit 65255a8

Browse files
committed
feat: add solutions to lc problems: No.1197,2181
* No.1197.Minimum Knight Moves * No.2181.Merge Nodes in Between Zeros
1 parent 0f1aee6 commit 65255a8

File tree

8 files changed

+521
-13
lines changed

8 files changed

+521
-13
lines changed

solution/1100-1199/1197.Minimum Knight Moves/README.md

Lines changed: 109 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,14 @@
4646

4747
<!-- 这里可写通用的实现逻辑 -->
4848

49-
BFS 最短路模型。
49+
BFS 最短路模型。本题搜索空间不大,可以直接使用朴素 BFS,以下题解中还提供了双向 BFS 的题解代码,仅供参考。
50+
51+
双向 BFS 是 BFS 常见的一个优化方法,主要实现思路如下:
52+
53+
1. 创建两个队列 q1, q2 分别用于“起点 -> 终点”、“终点 -> 起点”两个方向的搜索;
54+
2. 创建两个哈希表 m1, m2 分别记录访问过的节点以及对应的扩展次数(步数);
55+
3. 每次搜索时,优先选择元素数量较少的队列进行搜索扩展,如果在扩展过程中,搜索到另一个方向已经访问过的节点,说明找到了最短路径;
56+
4. 只要其中一个队列为空,说明当前方向的搜索已经进行不下去了,说明起点到终点不连通,无需继续搜索。
5057

5158
<!-- tabs:start -->
5259

@@ -145,15 +152,14 @@ class Solution {
145152

146153
```java
147154
class Solution {
148-
private int base = 310;
149155
private int n = 700;
150156

151157
public int minKnightMoves(int x, int y) {
152158
if (x == 0 && y == 0) {
153159
return 0;
154160
}
155-
x += base;
156-
y += base;
161+
x += 310;
162+
y += 310;
157163
Map<Integer, Integer> m1 = new HashMap<>();
158164
Map<Integer, Integer> m2 = new HashMap<>();
159165
m1.put(310 * n + 310, 0);
@@ -172,10 +178,10 @@ class Solution {
172178
}
173179

174180
private int extend(Map<Integer, Integer> m1, Map<Integer, Integer> m2, Queue<int[]> q) {
181+
int[][] dirs = {{-2, 1}, {-1, 2}, {1, 2}, {2, 1}, {2, -1}, {1, -2}, {-1, -2}, {-2, -1}};
175182
for (int k = q.size(); k > 0; --k) {
176183
int[] p = q.poll();
177184
int step = m1.get(p[0] * n + p[1]);
178-
int[][] dirs = {{-2, 1}, {-1, 2}, {1, 2}, {2, 1}, {2, -1}, {1, -2}, {-1, -2}, {-2, -1}};
179185
for (int[] dir : dirs) {
180186
int x = p[0] + dir[0];
181187
int y = p[1] + dir[1];
@@ -232,6 +238,57 @@ public:
232238
};
233239
```
234240
241+
双向 BFS:
242+
243+
```cpp
244+
typedef pair<int, int> PII;
245+
246+
class Solution {
247+
public:
248+
int n = 700;
249+
250+
int minKnightMoves(int x, int y) {
251+
if (x == 0 && y == 0) return 0;
252+
x += 310;
253+
y += 310;
254+
unordered_map<int, int> m1;
255+
unordered_map<int, int> m2;
256+
m1[310 * n + 310] = 0;
257+
m2[x * n + y] = 0;
258+
queue<PII> q1;
259+
queue<PII> q2;
260+
q1.push({310, 310});
261+
q2.push({x, y});
262+
while (!q1.empty() && !q2.empty())
263+
{
264+
int t = q1.size() <= q2.size() ? extend(m1, m2, q1) : extend(m2, m1, q2);
265+
if (t != -1) return t;
266+
}
267+
return -1;
268+
}
269+
270+
int extend(unordered_map<int, int>& m1, unordered_map<int, int>& m2, queue<PII>& q) {
271+
vector<vector<int>> dirs = {{-2, 1}, {-1, 2}, {1, 2}, {2, 1}, {2, -1}, {1, -2}, {-1, -2}, {-2, -1}};
272+
for (int k = q.size(); k > 0; --k)
273+
{
274+
auto p = q.front();
275+
q.pop();
276+
int i = p.first, j = p.second;
277+
int step = m1[i * n + j];
278+
for (auto& dir : dirs)
279+
{
280+
int x = i + dir[0], y = j + dir[1];
281+
if (m1.count(x * n + y)) continue;
282+
if (m2.count(x * n + y)) return step + 1 + m2[x * n + y];
283+
m1[x * n + y] = step + 1;
284+
q.push({x, y});
285+
}
286+
}
287+
return -1;
288+
}
289+
};
290+
```
291+
235292
### **Go**
236293

237294
```go
@@ -265,6 +322,53 @@ func minKnightMoves(x int, y int) int {
265322
}
266323
```
267324

325+
双向 BFS:
326+
327+
```go
328+
func minKnightMoves(x int, y int) int {
329+
if x == 0 && y == 0 {
330+
return 0
331+
}
332+
n := 700
333+
x, y = x+310, y+310
334+
q1, q2 := []int{310*700 + 310}, []int{x*n + y}
335+
m1, m2 := map[int]int{310*700 + 310: 0}, map[int]int{x*n + y: 0}
336+
dirs := [][]int{{-2, 1}, {-1, 2}, {1, 2}, {2, 1}, {2, -1}, {1, -2}, {-1, -2}, {-2, -1}}
337+
extend := func() int {
338+
for k := len(q1); k > 0; k-- {
339+
p := q1[0]
340+
q1 = q1[1:]
341+
i, j := p/n, p%n
342+
step := m1[i*n+j]
343+
for _, dir := range dirs {
344+
x, y := i+dir[0], j+dir[1]
345+
t := x*n + y
346+
if _, ok := m1[t]; ok {
347+
continue
348+
}
349+
if v, ok := m2[t]; ok {
350+
return step + 1 + v
351+
}
352+
m1[t] = step + 1
353+
q1 = append(q1, t)
354+
}
355+
}
356+
return -1
357+
}
358+
for len(q1) > 0 && len(q2) > 0 {
359+
if len(q1) <= len(q2) {
360+
q1, q2 = q2, q1
361+
m1, m2 = m2, m1
362+
}
363+
t := extend()
364+
if t != -1 {
365+
return t
366+
}
367+
}
368+
return -1
369+
}
370+
```
371+
268372
### **...**
269373

270374
```

solution/1100-1199/1197.Minimum Knight Moves/README_EN.md

Lines changed: 101 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,15 +133,14 @@ Two-end BFS:
133133

134134
```java
135135
class Solution {
136-
private int base = 310;
137136
private int n = 700;
138137

139138
public int minKnightMoves(int x, int y) {
140139
if (x == 0 && y == 0) {
141140
return 0;
142141
}
143-
x += base;
144-
y += base;
142+
x += 310;
143+
y += 310;
145144
Map<Integer, Integer> m1 = new HashMap<>();
146145
Map<Integer, Integer> m2 = new HashMap<>();
147146
m1.put(310 * n + 310, 0);
@@ -160,10 +159,10 @@ class Solution {
160159
}
161160

162161
private int extend(Map<Integer, Integer> m1, Map<Integer, Integer> m2, Queue<int[]> q) {
162+
int[][] dirs = {{-2, 1}, {-1, 2}, {1, 2}, {2, 1}, {2, -1}, {1, -2}, {-1, -2}, {-2, -1}};
163163
for (int k = q.size(); k > 0; --k) {
164164
int[] p = q.poll();
165165
int step = m1.get(p[0] * n + p[1]);
166-
int[][] dirs = {{-2, 1}, {-1, 2}, {1, 2}, {2, 1}, {2, -1}, {1, -2}, {-1, -2}, {-2, -1}};
167166
for (int[] dir : dirs) {
168167
int x = p[0] + dir[0];
169168
int y = p[1] + dir[1];
@@ -220,8 +219,61 @@ public:
220219
};
221220
```
222221
222+
Two-end BFS:
223+
224+
```cpp
225+
typedef pair<int, int> PII;
226+
227+
class Solution {
228+
public:
229+
int n = 700;
230+
231+
int minKnightMoves(int x, int y) {
232+
if (x == 0 && y == 0) return 0;
233+
x += 310;
234+
y += 310;
235+
unordered_map<int, int> m1;
236+
unordered_map<int, int> m2;
237+
m1[310 * n + 310] = 0;
238+
m2[x * n + y] = 0;
239+
queue<PII> q1;
240+
queue<PII> q2;
241+
q1.push({310, 310});
242+
q2.push({x, y});
243+
while (!q1.empty() && !q2.empty())
244+
{
245+
int t = q1.size() <= q2.size() ? extend(m1, m2, q1) : extend(m2, m1, q2);
246+
if (t != -1) return t;
247+
}
248+
return -1;
249+
}
250+
251+
int extend(unordered_map<int, int>& m1, unordered_map<int, int>& m2, queue<PII>& q) {
252+
vector<vector<int>> dirs = {{-2, 1}, {-1, 2}, {1, 2}, {2, 1}, {2, -1}, {1, -2}, {-1, -2}, {-2, -1}};
253+
for (int k = q.size(); k > 0; --k)
254+
{
255+
auto p = q.front();
256+
q.pop();
257+
int i = p.first, j = p.second;
258+
int step = m1[i * n + j];
259+
for (auto& dir : dirs)
260+
{
261+
int x = i + dir[0], y = j + dir[1];
262+
if (m1.count(x * n + y)) continue;
263+
if (m2.count(x * n + y)) return step + 1 + m2[x * n + y];
264+
m1[x * n + y] = step + 1;
265+
q.push({x, y});
266+
}
267+
}
268+
return -1;
269+
}
270+
};
271+
```
272+
223273
### **Go**
224274

275+
Two-end BFS:
276+
225277
```go
226278
func minKnightMoves(x int, y int) int {
227279
x, y = x+310, y+310
@@ -253,6 +305,51 @@ func minKnightMoves(x int, y int) int {
253305
}
254306
```
255307

308+
```go
309+
func minKnightMoves(x int, y int) int {
310+
if x == 0 && y == 0 {
311+
return 0
312+
}
313+
n := 700
314+
x, y = x+310, y+310
315+
q1, q2 := []int{310*700 + 310}, []int{x*n + y}
316+
m1, m2 := map[int]int{310*700 + 310: 0}, map[int]int{x*n + y: 0}
317+
dirs := [][]int{{-2, 1}, {-1, 2}, {1, 2}, {2, 1}, {2, -1}, {1, -2}, {-1, -2}, {-2, -1}}
318+
extend := func() int {
319+
for k := len(q1); k > 0; k-- {
320+
p := q1[0]
321+
q1 = q1[1:]
322+
i, j := p/n, p%n
323+
step := m1[i*n+j]
324+
for _, dir := range dirs {
325+
x, y := i+dir[0], j+dir[1]
326+
t := x*n + y
327+
if _, ok := m1[t]; ok {
328+
continue
329+
}
330+
if v, ok := m2[t]; ok {
331+
return step + 1 + v
332+
}
333+
m1[t] = step + 1
334+
q1 = append(q1, t)
335+
}
336+
}
337+
return -1
338+
}
339+
for len(q1) > 0 && len(q2) > 0 {
340+
if len(q1) <= len(q2) {
341+
q1, q2 = q2, q1
342+
m1, m2 = m2, m1
343+
}
344+
t := extend()
345+
if t != -1 {
346+
return t
347+
}
348+
}
349+
return -1
350+
}
351+
```
352+
256353
### **...**
257354

258355
```

0 commit comments

Comments
 (0)