C代码:二分查找 + BFS
// 题意:最开始下雨,水位必须淹没对应的两个位置,才能游过去!
// 相当于,就是找最大值!
const int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
bool check(int** grid, int m, int n, int mid) {
if (grid[0][0] > mid) { // 相比[1631. 最小体力消耗路径] 多的部分
return false; // 下面校验的是四个方向的点,当前点也需要校验
}
int visited[m][n];
memset(visited, 0, sizeof(int) * m * n);
visited[0][0] = 1;
int que[m * n][2];
memset(que, 0, sizeof(int) * m * n * 2);
int qhead = 0;
int qtail = 0;
que[qtail][0] = 0;
que[qtail++][1] = 0;
while (qhead < qtail) {
int x = que[qhead][0];
int y = que[qhead++][1];
for (int i = 0; i < 4; ++i) { // BFS
int dx = x + dir[i][0];
int dy = y + dir[i][1];
if (dx >= 0 && dx < m && dy >= 0 && dy < n && visited[dx][dy] != 1 && grid[dx][dy] <= mid) {
visited[dx][dy] = 1;
que[qtail][0] = dx;
que[qtail++][1] = dy;
}
}
}
return visited[m - 1][n - 1] == 1;
}
int swimInWater(int** grid, int gridSize, int* gridColSize){
int m = gridSize, n = gridColSize[0];
int left = 0, right = m * m - 1;
int ans = 0;
while (left <= right) { // 左闭右闭
int mid = (left + right) / 2;
if (check(grid, m, n, mid)) { // mid这个高度能进行到最后,还需要减小;
ans = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
return ans;
}
java:DFS + 二分
public class Solution {
private int N;
public static final int[][] DIRECTIONS = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
public int swimInWater(int[][] grid) {
this.N = grid.length;
int left = 0;
int right = N * N - 1;
while (left < right) { // 左闭右开
int mid = (left + right) / 2; // left + right 不会溢出 l + ((r-l) >> 1)
boolean[][] visited = new boolean[N][N];
if (grid[0][0] <= mid && dfs(grid, 0, 0, visited, mid)) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
private boolean dfs(int[][] grid, int x, int y, boolean[][] visited, int threshold) {
visited[x][y] = true;
for (int[] direction : DIRECTIONS) {
int newX = x + direction[0];
int newY = y + direction[1];
if (inArea(newX, newY) && !visited[newX][newY] && grid[newX][newY] <= threshold) {
if (newX == N - 1 && newY == N - 1) {
return true;
}
if (dfs(grid, newX, newY, visited, threshold)) {
return true;
}
}
}
return false;
}
private boolean inArea(int x, int y) {
return x >= 0 && x < N && y >= 0 && y < N;
}
}