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 <= grid.length == grid[0].length <= 100
grid[i][j]
is0
or1
题目链接:https://leetcode-cn.com/problems/as-far-from-land-as-possible/
思路
法一:多源BFS
这道题用一般思路想,就是对每个land做一次向四周的water扩散一遍,每次扩散时water所用距离取多次的最小值。时间复杂度是O(n*n*land),这种方法在land多的情况下较慢。
多源BFS就是用于解决这种多个出发点的题目。
多源BFS的实现思路:每一轮遍历,从上一轮更新的节点向四周多走1步去更新节点,直到所有节点都被更新过一次。
时间复杂度是O(n*n*turn),只和所求的最长距离有关,和land数量无关。
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;
}
};