得分最高的路径
难度:
标签:
题目描述
代码结果
运行时间: 278 ms, 内存: 21.2 MB
import java.util.PriorityQueue;
import java.util.stream.IntStream;
class Solution {
// 定义一个方向数组,表示四个方向(上,下,左,右)
private static final int[][] DIRECTIONS = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
public int maximumMinimumPath(int[][] grid) {
int m = grid.length;
int n = grid[0].length;
boolean[][] visited = new boolean[m][n];
// 最大堆,按照路径上最小值排序
PriorityQueue<int[]> maxHeap = new PriorityQueue<>((a, b) -> b[0] - a[0]);
maxHeap.offer(new int[]{grid[0][0], 0, 0});
visited[0][0] = true;
while (!maxHeap.isEmpty()) {
int[] current = maxHeap.poll();
int score = current[0], x = current[1], y = current[2];
// 到达终点,返回路径得分
if (x == m - 1 && y == n - 1) {
return score;
}
IntStream.range(0, 4)
.mapToObj(i -> new int[]{x + DIRECTIONS[i][0], y + DIRECTIONS[i][1]})
.filter(p -> p[0] >= 0 && p[0] < m && p[1] >= 0 && p[1] < n && !visited[p[0]][p[1]])
.forEach(p -> {
visited[p[0]][p[1]] = true;
maxHeap.offer(new int[]{Math.min(score, grid[p[0]][p[1]]), p[0], p[1]});
});
}
return -1; // 不会到达这里,题目保证有路径
}
}
解释
方法:
这个题解利用了二分查找和深度优先搜索(DFS)的方法来解决问题。首先,定义了一个辅助函数 exist(val),该函数通过DFS检查是否可以从网格的左上角(0,0)移动到右下角(m-1,n-1),同时确保路径上的最小值至少为val。在主函数中,通过二分查找在可能的值域中搜索可以实现这一条件的最大val。这种方法首先设定搜索的范围为两端起点和终点的最小值,然后不断调整搜索范围,直到找到最大的符合条件的val。
时间复杂度:
O(m*n*log(min(grid[0][0], grid[-1][-1])))
空间复杂度:
O(m*n)
代码细节讲解
🦆
在二分查找中,你是如何确定最初的搜索范围 `l` 和 `r` 为0和网格左上角与右下角的最小值?这是否保证了覆盖所有可能的路径值?
▷🦆
题解中的`exist(val)`函数通过DFS确保路径上的每个点的值不小于`val`。这种方法在找到存在的最小值后是否直接停止搜索,还是会继续探索其他可能的路径?
▷🦆
为什么在二分查找的过程中选择将`mid`更新为`(l + r + 1) // 2`而不是`(l + r) // 2`?这种选择对算法有何影响?
▷🦆
在`exist`函数中,如果当前点`(x, y)`已访问,为何还需要再次检查其四个方向的邻接点?这样做是否会导致不必要的重复计算?
▷