bobo老师,除了用Dijkstra之外,我尝试用二分搜索+BFS解决leetcode 505 The Maze II,但是只有70/78个case能通过,不知为何。能否请您拨冗看下代码,思路出在哪里?
我的思路是。因为maze矩阵的长、宽的范围是[0,100],所以二分的上下界是[0, 10001]。二分的目的是,找到start到destination的最短距离,如果不能到达,返回-1。 每次二分搜索确定一个值len,相当于给bfs添加了一个剪枝策略,当走过的distance大于len时,停止当前搜索。如果在len的限制下找到了从start到destination的路径,则利用二分继续向下寻找更小的distance。
但是在一个错误用例上,我的输出是204,正确答案是192。因为数据范围很大,我不太确定问题出在哪,所以想请您看下思路和代码哪里出现了问题,谢谢老师!
class Solution { private int[] dx = {1, 0, -1, 0}; private int[] dy = {0, 1, 0, -1}; public int shortestDistance(int[][] maze, int[] start, int[] destination) { int l = 1, r = 10001; while (l < r) { int mid = l + (r - l) / 2; if (hasPath(mid, maze, start, destination)) r = mid; else l = mid + 1; } return l == 10001 ? -1 : l; } private boolean hasPath(int len, int[][] maze, int[] start, int[] destination) { int m = maze.length; int n = maze[0].length; boolean[][] visited = new boolean[m][n]; Queue<int[]> q = new ArrayDeque<>(); q.offer(new int[]{start[0] * n + start[1], 0}); visited[start[0]][start[1]] = true; while (!q.isEmpty()) { int x = q.peek()[0] / n; int y = q.peek()[0] % n; int distance = q.peek()[1]; q.poll(); if (distance + 1 > len) continue; for (int k = 0; k < 4; k++) { int nx = x + dx[k]; int ny = y + dy[k]; int steps = 1; if (!inArea(nx, ny, maze) || visited[nx][ny] || maze[nx][ny] == 1) continue; while (inArea(nx, ny, maze) && maze[nx][ny] == 0) { nx += dx[k]; ny += dy[k]; steps++; } // 恢复最后一个合法状态 nx -= dx[k]; ny -= dy[k]; steps--; // 剪枝 if (distance + steps > len) continue; if (nx == destination[0] && ny == destination[1]) return true; if (!visited[nx][ny]) { q.offer(new int[]{nx*n + ny, distance + steps}); visited[nx][ny] = true; } } } return false; } private boolean inArea(int x, int y, int[][] maze) { return x >= 0 && x < maze.length && y >= 0 && y < maze[0].length; } }