【leetcode】【medium】【每日一题】1162. As Far from Land as Possible​​​​​​​

230 篇文章 0 订阅

1162. As Far from Land as Possible

Given an N x N grid containing only values 0 and 1, where 0 represents water and 1 represents land, find a water cell such that its distance to the nearest land cell is maximized and return the distance.

The distance used in this problem is the Manhattan distance: the distance between two cells (x0, y0) and (x1, y1) is |x0 - x1| + |y0 - y1|.

If no land or water exists in the grid, return -1.

Example 1:

 

Input: [[1,0,1],[0,0,0],[1,0,1]]
Output: 2
Explanation: 
The cell (1, 1) is as far as possible from all the land with distance 2.

Example 2:

 

Input: [[1,0,0],[0,0,0],[0,0,0]]
Output: 4
Explanation: 
The cell (2, 2) is as far as possible from all the land with distance 4.

Note:

  1. 1 <= grid.length == grid[0].length <= 100
  2. grid[i][j] is 0 or 1

题目链接:https://leetcode-cn.com/problems/as-far-from-land-as-possible/

 

思路

法一:多源BFS

这道题用一般思路想,就是对每个land做一次向四周的water扩散一遍,每次扩散时water所用距离取多次的最小值。时间复杂度是O(n*n*land),这种方法在land多的情况下较慢。

多源BFS就是用于解决这种多个出发点的题目。

多源BFS的形象解释:https://leetcode-cn.com/problems/as-far-from-land-as-possible/solution/zhen-liang-yan-sou-huan-neng-duo-yuan-kan-wan-miao/

多源BFS的实现思路:每一轮遍历,从上一轮更新的节点向四周多走1步去更新节点,直到所有节点都被更新过一次。

时间复杂度是O(n*n*turn),只和所求的最长距离有关,和land数量无关。

实现代码的参考:https://leetcode-cn.com/problems/as-far-from-land-as-possible/solution/lu-di-bu-duan-chang-da-zhi-dao-fu-gai-zheng-ge-di-/

class Solution {
public:
    int maxDistance(vector<vector<int>>& grid) {
        int n = grid.size();
        if(n==0) return -1;
        int land = 0, water, turn=0;
        for(int i=0; i<n; ++i){
            for(int j=0; j<n; ++j){
                if(grid[i][j]==1){
                    ++land;
                }
            }
        }
        if(land==0||land==n*n) {
            return -1;
        }
        water = n*n-land;
        while(water>0){
            ++turn;
            for(int i=0; i<n; ++i){
                for(int j=0; j<n; ++j){
                    if(grid[i][j]==turn){
                        if(i>0 && grid[i-1][j]==0){
                            grid[i-1][j] = turn+1;
                            --water;
                        }
                        if(i+1<n && grid[i+1][j]==0){
                            grid[i+1][j] = turn+1;
                            --water;
                        }
                        if(j>0 && grid[i][j-1]==0){
                            grid[i][j-1] = turn+1;
                            --water;
                        }
                        if(j+1<n && grid[i][j+1]==0){
                            grid[i][j+1] = turn+1;
                            --water;
                        }
                    }
                }
            }
        }
        return turn;
    }
};

 

法二:2个方向的dp

扩散要么从左上方来,要么从右下方来,因此从两个方向做2次dp。

class Solution {
public:
    int maxDistance(vector<vector<int>>& grid) {
        int n = grid.size();
        if(n==0) return -1;
        int res = 0, land = 0;
        for(int i=0; i<n; ++i){
            for(int j=0; j<n; ++j){
                if(grid[i][j]!=1){
                    int tmp = INT_MAX-1;
                    if(i>0) tmp = min(tmp, grid[i-1][j]+1);
                    if(j>0) {
                        tmp = min(tmp, grid[i][j-1]+1);
                    }
                    grid[i][j] = tmp;
                }else{
                    ++land;
                }
            }
        }
        if( land==0 ||land==n*n) return -1;
        for(int i=n-1; i>=0; --i){
            for(int j=n-1; j>=0; --j){
                if(grid[i][j]!=1){
                    int tmp = grid[i][j];
                    if(i+1<n) tmp = min(tmp, grid[i+1][j]+1);
                    if(j+1<n) tmp = min(tmp, grid[i][j+1]+1);
                    grid[i][j] = tmp;
                    res = max(res, tmp);
                }
            }
        }
        return res-1;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值