778. 水位上升的泳池中游泳(DFS+二分)

这个题目,用搜索做是很正常的想法 ,于是我就这样交代码了;
由于题给测试数据不大,200ms还是过了。

时间复杂度: O ( n 4 ) O(n^4) O(n4)

const int dx[] = {
     -1,0,1,0};
const int dy[] = {
     0,1,0,-1};

class Solution {
     
public:
    int n,t;
    bool vis[51][51];
    int swimInWater(vector<vector<int>>& grid) {
     
        n=grid.size();
        for(t=0;t<n*n;t++){
     
            if(grid[0][0]<=t){
     
                memset(vis,0,sizeof(vis)); //每次dfs,都要刷新一下
                if(dfs(0,0,grid)){
     
                    return t;
                }
            }
        }
        return n*n-1;
    }
    bool dfs(int x,int y,vector<vector<int>>& grid){
     
        // cout<
        if(x==n-1 && y==n-1){
     
            return true;
        }
        vis[x][y] = 1;
        for(int k=0;k<4;k++){
     
            int nx = x + dx[k];
            int ny = y + dy[k];
            if(nx>=0&&ny>=0&&nx<n&&ny<n && grid[nx][ny]<=t && !vis[nx][ny]){
     
                if(dfs(nx,ny,grid)){
     
                    return true;
                }
	 // vis[nx,ny] = 0;这个地方不需要也不能还原现场,否则会冗余搜索。
            }
        }
        return false;
    }
};

然后是怎么想到二分的呢?dfs()是一个关于时间t的函数,返回true 或false,相当于是在[1,n*n-1]这个区间猜一个数,刚好处于一个临界点(超过这个临界点都是true,不到临界点都是false)。
这不就是一个二分应用里面的一个猜大小数字的小游戏吗?
d f s ( t ) = { 0 1 , t ∈ [ 1 , n 2 − 1 ] dfs(t)=\begin{cases} 0\\ 1 \end{cases} ,t\in [1,n^2-1] dfs(t)={ 01,t[1,n21]

时间复杂度 O ( l o g ( n 2 ) ∗ n 2 ) = O ( l o g ( n ) n 2 ) O(log(n^2)*n^2)=O(log(n)n^2) O(log(n2)n2)=O(log(n)n2)

const int dx[] = {
     -1,0,1,0};
const int dy[] = {
     0,1,0,-1};

class Solution {
     
public:
    int n;
    bool vis[51][51];
    int swimInWater(vector<vector<int>>& grid) {
     
        n=grid.size();
        int l = grid[0][0], r = n*n-1,mid;
        while(l<r){
     
            int mid = (l+r)/2;
            memset(vis,0,sizeof(vis));
            if(dfs(0,0,mid,grid)){
     
                r = mid;
            }else{
     
                l = mid +1;
            }
        }
        return l;
    }
    bool dfs(int x,int y,int t,vector<vector<int>>& grid){
     
        if(x==n-1 && y==n-1){
     
            return true;
        }
        vis[x][y] = 1;
        for(int k=0;k<4;k++){
     
            int nx = x + dx[k];
            int ny = y + dy[k];
            if(nx>=0&&ny>=0&&nx<n&&ny<n && grid[nx][ny]<=t && !vis[nx][ny]){
     
                if(dfs(nx,ny,t,grid)){
     
                    return true;
                }
                // vis[nx][ny] = 0;
            }
        }
        return false;
    }

};

这里,我也用并查集做了一下,原理是一样的。

const int dx[] = {
     -1,0,1,0};
const int dy[] = {
     0,1,0,-1};
struct UFS{
     
    int f[50*50+10];
    UFS(){
     
        for(int i=0;i<50*50+10;i++){
     
            f[i]=i;
        }
    }
    int find(int x){
     
        return x==f[x]?x:f[x]=find(f[x]);
    }
    void merge(int x,int y){
     
        f[find(x)] = find(y);
    }
};
class Solution {
     
public:
    int swimInWater(vector<vector<int>>& grid) {
     
        int n = grid.size(),t;
        int l= grid[0][0],r=n*n-1;
        while(l<r){
     
            int mid = (l+r)/2;
            UFS ufs;
            for(int x=0;x<n;x++){
     
                for(int y=0;y<n;y++){
     
                    if(grid[x][y]>mid){
     
                        continue;
                    }
                    for(int k=0;k<4;k++){
     
                        int nx = x + dx[k];
                        int ny = y + dy[k];
                        if(nx>=0 && ny>=0 && nx<n && ny<n && grid[nx][ny]<=mid){
     
                            ufs.merge(x*50+y,nx*50+ny);
                        }
                    }
                }
            }
            if(ufs.find(0)==ufs.find((n-1)*50+(n-1))){
     
                r = mid;
            }else{
     
                l = mid+1;
            }
        }
        return l;
    }
};

这题还有用优先队列做的,暂时先搁着吧。
以后再补。

你可能感兴趣的:(LeetCode,#,LC深度优先搜索,#,LC二分,leetcode,dfs,数据结构,算法)