Imagine you are in a flooded grid. The water rises every minute. You start at the top-left corner and must reach the bottom-right. Each cell contains the time when it becomes swimmable. You can only swim into a cell if the water has risen to at least that cell's value. What is the minimum time you need to reach the destination?
用白话说就是:
每个格子是个水坑,数字表示水涨到那个高度才能游过去。你能上下左右游,目标是从左上角游到右下角,用最小时间达成目标。
表面看是 BFS,实则是 Dijkstra 的最小路径变种。我们不是在乎总花费最小,而是在乎 路径上遇到的最大数字最小。
🎯关键词:
- 最小堆(PriorityQueue)
- cost 表示当前路径中遇到的最大格子值
- Dijkstra思想:总是从当前可达的最小代价节点扩展
- visited数组防止重复访问
class Solution { private static final int[][] DIRS = new int[][]{{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
public int swimInWater(int[][] grid) {
if (grid == null || grid.length == 0 || grid[0].length == 0) {
return 0;
}
PriorityQueue<Element> minHeap = new PriorityQueue<>();
minHeap.offer(new Element(0, 0, grid[0][0]));
boolean[][] visited = new boolean[grid.length][grid[0].length];
visited[0][0] = true;
while (!minHeap.isEmpty()) {
Element cur = minHeap.poll();
for (int[] dir : DIRS) {
int neiX = cur.x + dir[0];
int neiY = cur.y + dir[1];
if (isValid(grid, neiX, neiY) && !visited[neiX][neiY]) {
int neiCost = Math.max(cur.cost, grid[neiX][neiY]);
if (neiX == grid.length - 1 && neiY == grid[0].length - 1) {
return neiCost;
}
minHeap.offer(new Element(neiX, neiY, neiCost));
visited[neiX][neiY] = true;
}
}
}
return 0;
}
private boolean isValid(int[][] grid, int i, int j) {
return i >= 0 && i < grid.length && j >= 0 && j < grid[0].length;
}
static class Element implements Comparable<Element> {
int x;
int y;
int cost;
Element(int x, int y, int cost) {
this.x = x;
this.y = y;
this.cost = cost;
}
@Override
public int compareTo(Element other) {
return Integer.compare(this.cost, other.cost);
}
}
封装了 (x, y, cost),可读性大大提升,compareTo 优雅定义优先级。用 Java 写这题时,封装类是强烈推荐的写法,避免了混乱的多变量堆操作。
🗺️图解:解法演示(伪图)
每个格子代表水位:
[0, 2, 3]
[1, 4, 6]
[5, 8, 7]
起点 grid[0][0] = 0
目标 grid[2][2] = 7
最优路径是:
(0,0) → (1,0)=1 → (2,0)=5 → (2,1)=8 → (2,2)=7
路径最大值是 8
但还有更优解!
(0,0) → (0,1)=2 → (1,1)=4 → (1,2)=6 → (2,2)=7
路径最大值是 7 ✅
所以答案是 7
🧪时间复杂度分析
- 总共访问所有节点一次:O(n²)
- 每次堆操作:O(log n²)
- 总时间复杂度:O(n² log n)
空间复杂度同样是 O(n²),主要用于 visited 数组和优先队列。
我们追求的不是最短距离,而是路径上最高的障碍最小!Dijkstra 在这里被用来处理“最大值路径”的问题,而不是最小和,这种转换非常经典且实用。