迷宫 III
难度:
标签:
题目描述
代码结果
运行时间: 33 ms, 内存: 16.3 MB
/*
* 思路:
* 1. 使用广度优先搜索(BFS)在迷宫中寻找从起点到终点的最短路径。
* 2. 利用Java Streams来处理优先队列中的元素。
* 3. 路径信息通过字符串的形式累积,优先选择字典序小的路径。
*/
import java.util.*;
import java.util.stream.Stream;
public class SolutionStream {
private static final int[][] DIRECTIONS = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
private static final char[] DIR_CHARS = {'u', 'd', 'l', 'r'};
public String findShortestWay(int[][] maze, int[] ball, int[] hole) {
int m = maze.length, n = maze[0].length;
PriorityQueue<Point> pq = new PriorityQueue<>((a, b) -> a.dist == b.dist ? a.path.compareTo(b.path) : a.dist - b.dist);
pq.offer(new Point(ball[0], ball[1], 0, ""));
boolean[][] visited = new boolean[m][n];
visited[ball[0]][ball[1]] = true;
while (!pq.isEmpty()) {
Point p = pq.poll();
if (p.x == hole[0] && p.y == hole[1]) return p.path;
for (int i = 0; i < DIRECTIONS.length; i++) {
int[] dir = DIRECTIONS[i];
int x = p.x, y = p.y, dist = p.dist;
while (x + dir[0] >= 0 && x + dir[0] < m && y + dir[1] >= 0 && y + dir[1] < n && maze[x + dir[0]][y + dir[1]] == 0) {
x += dir[0];
y += dir[1];
dist++;
if (x == hole[0] && y == hole[1]) break;
}
if (visited[x][y]) continue;
visited[x][y] = true;
pq.offer(new Point(x, y, dist, p.path + DIR_CHARS[i]));
}
}
return "impossible";
}
private static class Point {
int x, y, dist;
String path;
Point(int x, int y, int dist, String path) {
this.x = x;
this.y = y;
this.dist = dist;
this.path = path;
}
}
}
解释
方法:
该题解使用了Dijkstra算法来寻找从起点到终点的最短路径。与普通的Dijkstra算法不同的是,除了记录最短距离外,还需要记录到达每个位置的路线。具体实现时,使用优先队列来存储当前探索到的位置,每次取出距离最小的位置进行扩展。对于每个位置,尝试向四个方向移动,直到撞墙或到达终点。如果到达一个之前未探索过的位置,则更新其距离并记录路线;如果到达一个已探索过的位置,且距离相等,则在该位置的路线中追加新的路线。最后,如果到达终点,则返回字典序最小的路线;如果无法到达终点,则返回'impossible'。
时间复杂度:
O(mnlog(mn))
空间复杂度:
O(mn(m+n))
代码细节讲解
🦆
在使用Dijkstra算法时,你是如何处理迷宫中的'撞墙'逻辑?在代码中似乎有回退一步的操作,请问这是怎样实现的?
▷🦆
此题解中提到,如果到达一个已探索过的位置且距离相等,则在该位置的路线中追加新的路线。请问这种处理对于Dijkstra算法的效率有何影响?
▷🦆
题解中提到当到达终点时,返回字典序最小的路线。请问是否有可能存在多条相同长度但字典序不同的最短路径?如果有,该如何决定返回哪一条?
▷🦆
在更新距离数组和路径字典时,如果新计算的距离小于之前记录的距离,会替换原有的路径。这种操作是否可能导致先前的一些优秀路径被遗漏?
▷