778 水位上升的泳池中游泳
阿新 • • 發佈:2021-02-01
技術標籤:LeetCode
題目描述:
在一個 N x N 的座標方格 grid 中,每一個方格的值 grid[i][j] 表示在位置 (i,j) 的平臺高度。
現在開始下雨了。當時間為 t 時,此時雨水導致水池中任意位置的水位為 t 。你可以從一個平臺遊向四周相鄰的任意一個平臺,但是前提是此時水位必須同時淹沒這兩個平臺。假定你可以瞬間移動無限距離,也就是預設在方格內部遊動是不耗時的。當然,在你游泳的時候你必須待在座標方格里面。
你從座標方格的左上平臺 (0,0) 出發。最少耗時多久你才能到達座標方格的右下平臺 (N-1, N-1)?
示例 1
輸入: [[0,2],[1,3]]
輸出: 3
時間為0時,你位於座標方格的位置為 (0, 0)。
此時你不能遊向任意方向,因為四個相鄰方向平臺的高度都大於當前時間為 0 時的水位。
等時間到達 3 時,你才可以遊向平臺 (1, 1). 因為此時的水位是 3,座標方格中的平臺沒有比水位 3 更高的,所以你可以遊向座標方格中的任意位置
示例2:
輸入: [[0,1,2,3,4],[24,23,22,21,5],[12,13,14,15,16],[11,17,18,19,20],[10,9,8,7,6]]
輸出: 16
解釋:
0 1 2 3 4
24 23 22 21 5
12 13 14 15 16
11 17 18 19 20
10 9 8 7 6
我們必須等到時間為 16,此時才能保證平臺 (0, 0) 和 (4, 4) 是連通的
提示:
2 <= N <= 50.
grid[i][j] 是 [0, …, N*N - 1] 的排列。
方法1:
主要思路:解題彙總連結
(1)二分;
(2)找出原陣列中的最大值和最小值作為二分的範圍;
(3)每次找出一箇中間值,判斷該值下是否能夠獲得到達終點,進一步縮小範圍;
class Solution {
public:
//判斷限制值mid下是否能夠到達終點
bool check(vector<vector<int>>&grid, const int& mid,int row,int col,vector<vector<bool>>&sign){
if(row==grid.size()-1&&col==grid[0].size()-1){
if(grid.back().back()>mid){
return false;
}
return true;
}
sign[row][col]=true;
if(grid[row][col]>mid){
sign[row][col]=true;
return false;
}
if(row>0&&!sign[row-1][col]){
if(check(grid,mid,row-1,col,sign)){
return true;
}
}
if(row+1<grid.size()&&!sign[row+1][col]){
if(check(grid,mid,row+1,col,sign)){
return true;
}
}
if(col>0&&!sign[row][col-1]){
if(check(grid,mid,row,col-1,sign)){
return true;
}
}
if(col+1<grid[0].size()&&!sign[row][col+1]){
if(check(grid,mid,row,col+1,sign)){
return true;
}
}
return false;
}
int swimInWater(vector<vector<int>>& grid) {
//確定最大值和最下值,既二分的範圍
int left=0;
int right=0;
for(vector<int>&vec:grid){
for(int& i:vec){
right=max(right,i);
}
}
int res=0;
//二分
while(left<=right){
int mid=left+(right-left)/2;
vector<vector<bool>> sign(grid.size(),vector<bool>(grid[0].size(),false));
if(check(grid,mid,0,0,sign)){
right=mid-1;
res=mid;
}
else{
left=mid+1;
}
}
return res;
}
};
方法2:
主要思路:
(1)優先佇列;
(2)每次將能夠到達的位置壓入到優先佇列中,最小堆,每次堆頂的元素即為當前所有位置中值最下的結點位置;
(3)然後重新判讀能否有新的能夠到達的位置壓入佇列中;
(4)對於訪問過的位置,使用最大值INT_MAX進行標識;
class Solution {
public:
struct cmp{//比較函式
bool operator()(vector<int>&lhs,vector<int>&rhs) {
return lhs[0]>rhs[0];
}
};
int swimInWater(vector<vector<int>>& grid) {
priority_queue<vector<int>,vector<vector<int>>,cmp> q;
q.push({grid[0][0],0,0});//初始化
int rows=grid.size(),cols=grid[0].size();
int res=0;
while(!q.empty()){
int cur_v=q.top()[0];
int cur_r=q.top()[1];
int cur_c=q.top()[2];
q.pop();
res=max(res,cur_v);//更新可能的結果
if(cur_r==rows-1&&cur_c==cols-1){//達到了終點位置
return res;
}
grid[cur_r][cur_c]=INT_MAX;//標識訪問過的位置
//是否有新的位置加入
if(cur_r>0&&grid[cur_r-1][cur_c]!=INT_MAX){
q.push({grid[cur_r-1][cur_c],cur_r-1,cur_c});
}
if(cur_r+1<rows&&grid[cur_r+1][cur_c]!=INT_MAX){
q.push({grid[cur_r+1][cur_c],cur_r+1,cur_c});
}
if(cur_c>0&&grid[cur_r][cur_c-1]!=INT_MAX){
q.push({grid[cur_r][cur_c-1],cur_r,cur_c-1});
}
if(cur_c+1<cols&&grid[cur_r][cur_c+1]!=INT_MAX){
q.push({grid[cur_r][cur_c+1],cur_r,cur_c+1});
}
}
return res;
}
};