Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit eefb18f

Browse files
✨feat: Add 675
1 parent 952b2d3 commit eefb18f

File tree

2 files changed

+98
-1
lines changed

2 files changed

+98
-1
lines changed

‎Index/并查集.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
| 题目 | 题解 | 难度 | 推荐指数 |
22
| ------------------------------------------------------------ | ------------------------------------------------------------ | ---- | -------- |
33
| [417. 太平洋大西洋水流问题](https://leetcode-cn.com/problems/pacific-atlantic-water-flow/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/pacific-atlantic-water-flow/solution/by-ac_oier-do7d/) | 中等 | 🤩🤩🤩🤩🤩 |
4+
| [675. 为高尔夫比赛砍树](https://leetcode.cn/problems/cut-off-trees-for-golf-event/) | [LeetCode 题解链接](https://leetcode.cn/problems/cut-off-trees-for-golf-event/solution/by-ac_oier-ksth/) | 困难 | 🤩🤩🤩 |
45
| [765. 情侣牵手](https://leetcode-cn.com/problems/couples-holding-hands/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/couples-holding-hands/solution/liang-chong-100-de-jie-fa-bing-cha-ji-ta-26a6/) | 困难 | 🤩🤩🤩 |
56
| [778. 水位上升的泳池中游泳](https://leetcode-cn.com/problems/swim-in-rising-water/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/swim-in-rising-water/solution/gong-shui-san-xie-yi-ti-shuang-jie-krusk-7c6o/) | 困难 | 🤩🤩🤩 |
67
| [1020. 飞地的数量](https://leetcode-cn.com/problems/number-of-enclaves/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/number-of-enclaves/solution/gong-shui-san-xie-bing-cha-ji-dfs-yun-yo-oyh1/) | 中等 | 🤩🤩🤩 |

‎LeetCode/671-680/675. 为高尔夫比赛砍树(困难).md‎

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
这是 LeetCode 上的 **[675. 为高尔夫比赛砍树](https://leetcode.cn/problems/cut-off-trees-for-golf-event/solution/by-ac_oier-ksth/)** ,难度为 **困难**
44

5-
Tag : 「图论 BFS」、「AStar 算法」、「启发式搜索」
5+
Tag : 「图论 BFS」、「AStar 算法」、「启发式搜索」、「并查集」
66

77

88

@@ -221,6 +221,102 @@ class Solution {
221221

222222
---
223223

224+
### AStar 算法 + 并查集预处理无解
225+
226+
我们知道,AStar 算法使用到了「优先队列(堆)」来进行启发式搜索,而对于一些最佳路径方向与两点相对位置相反(例如 $T$ 在 $S$ 的右边,但由于存在障碍,最短路径需要先从左边绕一圈才能到 $T$),AStar 反而会因为优先队列(堆)而多一个 $\log$ 的复杂度。
227+
228+
因此一个可行的优化是,我们先提前处理「无解」的情况,常见的做法是在预处理过程中运用「并查集」来维护连通性。
229+
230+
这种对于不影响复杂度上界的预处理相比后续可能出现的大量无效搜索(最终无解)的计算量而言,是有益的。
231+
232+
代码:
233+
```Java
234+
class Solution {
235+
int N = 50;
236+
int[][] g = new int[N][N];
237+
int n, m;
238+
int[] p = new int[N * N + 10];
239+
List<int[]> list = new ArrayList<>();
240+
void union(int a, int b) {
241+
p[find(a)] = p[find(b)];
242+
}
243+
boolean query(int a, int b) {
244+
return find(a) == find(b);
245+
}
246+
int find(int x) {
247+
if (p[x] != x) p[x] = find(p[x]);
248+
return p[x];
249+
}
250+
int getIdx(int x, int y) {
251+
return x * m + y;
252+
}
253+
public int cutOffTree(List<List<Integer>> forest) {
254+
n = forest.size(); m = forest.get(0).size();
255+
// 预处理过程中,同时使用「并查集」维护连通性
256+
for (int i = 0; i < n * m; i++) p[i] = i;
257+
int[][] tempDirs = new int[][]{{0,-1},{-1,0}};
258+
for (int i = 0; i < n; i++) {
259+
for (int j = 0; j < m; j++) {
260+
g[i][j] = forest.get(i).get(j);
261+
if (g[i][j] > 1) list.add(new int[]{g[i][j], i, j});
262+
if (g[i][j] == 0) continue;
263+
// 只与左方和上方的区域联通即可确保不重不漏
264+
for (int[] di : tempDirs) {
265+
int nx = i + di[0], ny = j + di[1];
266+
if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
267+
if (g[nx][ny] != 0) union(getIdx(i, j), getIdx(nx, ny));
268+
}
269+
}
270+
}
271+
// 若不满足所有树点均与 (0,0),提前返回无解
272+
for (int[] info : list) {
273+
int x = info[1], y = info[2];
274+
if (!query(getIdx(0, 0), getIdx(x, y))) return -1;
275+
}
276+
Collections.sort(list, (a,b)->a[0]-b[0]);
277+
int x = 0, y = 0, ans = 0;
278+
for (int[] ne : list) {
279+
int nx = ne[1], ny = ne[2];
280+
int d = astar(x, y, nx, ny);
281+
if (d == -1) return -1;
282+
ans += d;
283+
x = nx; y = ny;
284+
}
285+
return ans;
286+
}
287+
int f(int X, int Y, int P, int Q) {
288+
return Math.abs(X - P) + Math.abs(Y - Q);
289+
}
290+
int[][] dirs = new int[][]{{0,1},{0,-1},{1,0},{-1,0}};
291+
int astar(int X, int Y, int P, int Q) {
292+
if (X == P && Y == Q) return 0;
293+
Map<Integer, Integer> map = new HashMap<>();
294+
PriorityQueue<int[]> q = new PriorityQueue<>((a,b)->a[0]-b[0]);
295+
q.add(new int[]{f(X, Y, P, Q), X, Y});
296+
map.put(getIdx(X, Y), 0);
297+
while (!q.isEmpty()) {
298+
int[] info = q.poll();
299+
int x = info[1], y = info[2], step = map.get(getIdx(x, y));
300+
for (int[] di : dirs) {
301+
int nx = x + di[0], ny = y + di[1], nidx = getIdx(nx, ny);
302+
if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
303+
if (g[nx][ny] == 0) continue;
304+
if (nx == P && ny == Q) return step + 1;
305+
if (!map.containsKey(nidx) || map.get(nidx) > step + 1) {
306+
q.add(new int[]{step + 1 + f(nx, ny, P, Q), nx, ny});
307+
map.put(nidx, step + 1);
308+
}
309+
}
310+
}
311+
return -1;
312+
}
313+
}
314+
```
315+
* 时间复杂度:启发式搜索分析时空复杂度意义不大
316+
* 空间复杂度:启发式搜索分析时空复杂度意义不大
317+
318+
---
319+
224320
### 最后
225321

226322
这是我们「刷穿 LeetCode」系列文章的第 `No.675` 篇,系列开始于 2021年01月01日,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /