首页 > 其他 > 详细

leetcode 778. Swim in Rising Water

时间:2020-03-31 12:30:44      阅读:62      评论:0      收藏:0      [点我收藏+]

解法一:题目可以理解为从(0,0)到(n-1,n-1)的所有路径的最大海拔的最小值,max(路径最大海拔)。那么对于每一个点,求从(0 , 0)到该点的所有路径的最大值的最小值。可以用bfs来做,用maxele存储从(0,0)到该点的路径中的最大值的最小值,用inque防止cell在队列中重复存在;

class Solution {
public:
    int swimInWater(vector<vector<int>>& grid) {
        
        int n = grid.size() ;
        vector<vector<int>> inque(n , vector<int>(n , 0)) , maxele(n , vector<int>(n , INT_MAX)) ;
        
        queue<int> q ;
        q.push(0) ;
        inque[0][0] = 1 ;
        maxele[0][0] = grid[0][0] ;
        
        while(!q.empty())
        {
            int i = q.front() / n , j = q.front() % n ;
            q.pop() ;
            inque[i][j] = 0 ;
            
            for(int k = 0 ; k < 4 ; k++)
            {
                int ni = i + dir[k] , nj = j + dir[k+1] ;
                if(ni < 0 || ni >= n || nj < 0 || nj >= n) continue;
                
                if(max(maxele[i][j] , grid[ni][nj]) < maxele[ni][nj]) 
                {
                    maxele[ni][nj] = max(maxele[i][j] , grid[ni][nj]) ;
                    if(!inque[ni][nj]) 
                    {
                        q.push(ni * n + nj) ;
                        inque[ni][nj] = 1 ;
                    }
                }
            }
        }
        
        return maxele[n-1][n-1]; 
    }
    
private:
    
    vector<int> dir = {-1, 0 , 1, 0 , -1}; 
};

  

解法二:

  cell中的海拔是[0 , N*N - 1]的排列,所以所求的least time一定处于[0 , N*N-1]的范围内,可以使用二分搜索;给定x,如果找到一条路径,路径中的每一个cell的海拔都小于或等于x,则r = x ;否则l = x + 1 ;(路径搜索可以用dfs或者bfs)

dfs(使用dfs一定要记得写上递归基)(时间复杂度(O(N^2log(N^2))) , 8ms.因为只搜索一条可行路径,不需要遍历所有路径,相较bfs更快)

class Solution {
public:
    int swimInWater(vector<vector<int>>& grid) {
        
        int n = grid.size() ;
        int l = grid[0][0] , r = n * n - 1 ;
        
        while(l < r)
        {
            int mid = l + (r - l) / 2;
            if(valid(mid , grid)) r = mid ;
            else l = mid + 1 ;
        }
        
        return l ;
    }
    
private:
    
    vector<int> dir = {-1 , 0 , 1 , 0 , -1};
    
    bool valid(int x , vector<vector<int>>& grid)
    {
        int n = grid.size() ;
        vector<vector<int>> visited(n , vector<int>(n , 0));
        
        return dfs(0 , 0 , x , visited , grid) ;
    }
    
    bool dfs(int r , int c , int x , vector<vector<int>>& visited , vector<vector<int>> &grid)
    {
        int n = grid.size() ;
        
        if(r == n - 1 && c == n - 1) return true ;
        
        visited[r][c] = 1 ;
        
        for(int k = 0 ; k < 4 ; k++)
        {
            int nr = r + dir[k] , nc = c + dir[k+1] ;
            if(nr < 0 || nr >= n || nc < 0 || nc >= n || visited[nr][nc] || grid[nr][nc] > x) continue ;
            
            if(dfs(nr , nc , x , visited , grid)) return true; 
        }
        
        return false;
    }
};

 

bfs(28ms)

class Solution {
public:
    int swimInWater(vector<vector<int>>& grid) {
        
        int n = grid.size() ;
        int l = grid[0][0] , r = n * n - 1 ;
        
        while(l < r)
        {
            int mid = l + (r - l) / 2;
            if(bfs(mid , grid)) r = mid ;
            else l = mid + 1 ;
        }
        
        return l ;
    }
    
private:
    
    vector<int> dir = {-1 , 0 , 1 , 0 , -1};

    bool bfs(int x , vector<vector<int>>& grid)
    {
        int n = grid.size() ;
        vector<vector<int>> visited(n , vector<int>(n , 0));
        queue<int> q ;
        q.push(0) ;
        visited[0][0] = 1 ;
        
        while(!q.empty())
        {
            int r = q.front() / n , c = q.front() % n ;
            q.pop() ;
            
            if(r == n - 1 && c == n - 1) return true ;
            
            for(int k = 0 ; k < 4 ; k++)
            {
                int nr = r + dir[k] , nc = c + dir[k + 1]; 
                if(nr < 0 || nr >= n || nc < 0 || nc >= n || visited[nr][nc] || grid[nr][nc] > x) continue ;
                
                visited[nr][nc] = 1 ;
                q.push(nr * n + nc) ;
            }
        }
        
        return false;
    }
};

  

解法三:在搜索路径的过程中,我们优先选择目前为止搜索到的海拔最小的cell继续搜索,因为每个cell可以往四个方向搜索,所以任意两个cell都连通。所以可以用贪心的方法做, 如果不是任意两个cell都连通,就不能用贪心来做;

priority_queue , 在用priority_queue或者queue或者deque或stack的时候,记得要pop;(32ms)

class Solution {
public:
    int swimInWater(vector<vector<int>>& grid) 
    {
        int res = grid[0][0] , n = grid.size();
        
        priority_queue<pair<int,int> , vector<pair<int,int>> , greater<pair<int,int>> > q ;
        vector<vector<int>> vis(n , vector<int>(n , 0)) ;
        vector<int> dir = {-1 , 0 , 1 , 0 , -1} ;
        
        q.push({0 , 0}) ;
        vis[0][0] = 1 ;
        
        while(!q.empty())
        {
            int t = q.top().first , r = q.top().second / n , c = q.top().second % n ;
            q.pop() ;
            res = max(res , t) ;
            
            if(r == n - 1 && c == n - 1) break ;
            
            for(int k = 0 ; k < 4 ; k++)
            {
                int nr = r + dir[k] , nc = c + dir[k + 1] ;
                if(nr < 0 || nr >= n || nc < 0 || nc >= n || vis[nr][nc]) continue;
                
                q.push({grid[nr][nc] , nr * n + nc}) ;
                vis[nr][nc] = 1 ;
            }
        }
        
        return res; 
    }
       
};

  

 

leetcode 778. Swim in Rising Water

原文:https://www.cnblogs.com/mychen06/p/12602866.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!