Open azl397985856 opened 3 years ago
岛屿问题系列题, 一般是用dfs或bfs。 本题, 我打算使用bfs来做。
实现语言: C++
class Solution {
const int dx[4] = {0, 1, 0, -1};
const int dy[4] = {1, 0, -1, 0};
public:
int maxDistance(vector<vector<int>>& grid) {
int N = grid.size();
queue<pair<int, int>> q; // queue存储坐标值, 即 pair of {x, y}
vector<vector<int>> d(N, vector(N, 1000)); // 二维数组d[][]: 记录每个格子grid[i][j]的距离值
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
if (grid[i][j] == 1)
{
q.push(make_pair(i, j));
d[i][j] = 0;
}
}
while (!q.empty())
{
auto kvp = q.front();
q.pop();
for (int i = 0; i < 4; i++)
{
int newX = kvp.first + dx[i], newY = kvp.second + dy[i];
if (newX < 0 || newX >= N || newY < 0 || newY >= N) // 越界了, 跳过
continue;
if (d[newX][newY] > d[kvp.first][kvp.second] + 1) /* 如果从水域(值为0的格子)走到陆地(值为1的格子)或从陆地走到水域, 且新到达的位置之前没被访问过, 此时需要将其坐标加入队列, 并更新距离值d */
{
d[newX][newY] = d[kvp.first][kvp.second] + 1; /* 当前格子的上下左右4个方向之一走一步恰好使得曼哈顿距离增加1 */
q.push(make_pair(newX, newY));
}
}
}
int res = -1;
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
if (grid[i][j] == 0 && d[i][j] <= 200) /* 挑出访问过的水域位置(值为0的格子), 并维护这些格子中距离值d的最大值 */
res = max(res, d[i][j]);
}
}
return res;
}
};
利用BFS做组层遍历
第一层是所有的陆地,然后每一层向下一层水遍历,修改grid来来更新距离
from collections import deque
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
m, n = len(grid), len(grid[0])
queue = deque([(i, j) for i in range(m) for j in range(n) if grid[i][j] == 1])
level = 0
while queue:
queue_size = len(queue)
level += 1
for _ in range(queue_size):
c_i, c_j = queue.pop()
for delta_i, delta_j in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
new_i, new_j = c_i + delta_i, c_j + delta_j
if 0 <= new_i < m and 0 <= new_j < n and grid[new_i][new_j] == 0:
# print(new_i, new_j, grid[new_i][new_j], level)
grid[new_i][new_j] = -level
queue.appendleft((new_i, new_j))
return -min((grid[i][j] for i in range(m) for j in range(n))) or -1
Time O(mn)
Space O(mn)
BFS O(MN), O(MN)
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
M, N = len(grid), len(grid[0])
def neighbors(x, y):
dirs = [[0, 1], [1, 0], [-1, 0], [0, -1]]
for d in dirs:
nx, ny = x + d[0], y + d[1]
if 0 <= nx < M and 0 <= ny < N:
yield nx, ny
def get_distance(queue):
visited = set([(c[1], c[2]) for c in queue])
dist = -1
while queue:
dist, x, y = queue.popleft()
for nx, ny in neighbors(x, y):
if (nx, ny) not in visited:
visited.add((nx, ny))
queue.append((dist+1, nx, ny))
return dist if dist > 0 else -1
queue = deque()
for x in range(M):
for y in range(N):
if grid[x][y] == 1:
queue.append((0, x, y))
return get_distance(queue)
蔓延
这个行为,是可以从任意陆地/烂番茄的地方开始的,因此要么你逐个bfs然后更新最少时间,要么就模拟一起开始AC
class Solution {
public int maxDistance(int[][] grid) {
int max = Integer.MIN_VALUE;
Queue<int[]> q = new LinkedList<>();
for(int row = 0;row < grid.length;row++){
for(int col = 0;col < grid[0].length;col++){
if(grid[row][col] == 1){
q.add(new int[]{row, col});
}
}
}
if(q.size() == grid.length * grid[0].length || q.size() == 0){
return -1;
}
int[][] directions = new int[][]{{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
while(!q.isEmpty()){
int size = q.size();
for(int i = 0;i < size;i++){
int[] cur = q.poll();
int dis = grid[cur[0]][cur[1]] + 1;
for(int[] direction: directions){
int nrow = cur[0] + direction[0];
int ncol = cur[1] + direction[1];
if(nrow >= 0 && nrow < grid.length && ncol >= 0 && ncol < grid[0].length && grid[nrow][ncol] == 0){
grid[nrow][ncol] = dis;
q.add(new int[]{nrow, ncol});
}
}
}
}
for(int row = 0;row < grid.length;row++){
for(int col = 0;col < grid[0].length;col++){
max = Math.max(max, grid[row][col]);
}
}
return max - 1;
}
}
time: O(N^2),遍历每个cell space: O(N)
class Solution {
public int maxDistance(int[][] grid) {
Queue<int[]> queue = new LinkedList<>();
// 遍历所有的陆地
for (int row = 0; row < grid.length; row ++) {
for (int col = 0; col < grid[0].length; col ++) {
if (grid[row][col] == 1) {
queue.offer(new int[]{row, col});
}
}
}
int[][] dirs = new int[][] {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
int level = 0;
if (queue.isEmpty() || queue.size() == grid.length * grid[0].length) return -1;
while (!queue.isEmpty()) {
int cnt = queue.size();
for (int i = 0; i < cnt; i ++) {
int[] point = queue.poll();
for (int[] dir : dirs) {
int newX = point[0] + dir[0];
int newY = point[1] + dir[1];
if (isValid(grid, newX, newY)) {
grid[newX][newY] = 1;
queue.offer(new int[] {newX, newY});
}
}
}
level ++;
}
// 填到最后一个海水时,它也会遍历周围的海,所以返回的结果需要 - 1
return level - 1;
}
public boolean isValid(int grid[][], int r, int c) {
return r >= 0 && r < grid.length && c >= 0 && c < grid[0].length && grid[r][c] == 0;
}
}
bfs 类似 0,1矩阵
Java Code:
class Solution {
public int maxDistance(int[][] grid) {
// find a water cell such that its distance to the nearest land cell is maximized
// like (0, 1) matrix, find the shortest path to a land, keep an globalMax
// but what if there are more than 1 point satisfy the condition?
// offer all the initial points to queue which have values as 1
// we need to calculated the value for all the 0's, value is the shortest path to an island
int[][] directions = new int[][]{{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
Deque<int[]> queue = new ArrayDeque<>();
int m = grid.length;
int n = grid[0].length;
boolean[][] visited = new boolean[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 1) {
queue.offer(new int[]{i, j});
visited[i][j] = true;
}
}
}
int path = 0;
int maxPath = -1;
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
int[] cur = queue.poll();
int x = cur[0];
int y = cur[1];
if (grid[x][y] == 0) {
if (path > maxPath) {
maxPath = path;
}
}
for (int[] dir: directions) {
int newX = x + dir[0];
int newY = y + dir[1];
if (isValid(newX, newY, m, n) && !visited[newX][newY]) {
queue.offer(new int[]{newX, newY});
visited[newX][newY] = true;
}
}
}
path += 1;
}
return maxPath;
}
private boolean isValid(int x, int y, int m, int n) {
return x >= 0 && x < m && y >= 0 && y < n;
}
}
复杂度分析
var maxDistance = function(grid) {
let result = -1;
let queue = [];
const row = grid.length;
const col = grid[0].length;
// add 1s into queue for (let i=0; i<row; i++){ for (let j=0; j<col; j++){ if (grid[i][j] == 1){ queue.push([i, j]); }; }; };
// edge cases if (queue.length == 0 || queue.length == row*col){ return result; };
// do bfs const directions = [[1,0], [-1,0], [0,-1], [0,1]] while (queue.length > 0){ let length = queue.length; for (let k=0; k<length; k++){ let [i,j] = queue.shift(); for (let changes of directions){ let newI = i+changes[0]; let newJ = j+changes[1]; if (newI >= 0 && newI < row && newJ >= 0 && newJ < col){ if (grid[newI][newJ] === 0){ grid[newI][newJ] = -1; queue.push([newI, newJ]); }; }; }; }; result++; }; return result; };
#### Python Code
```Python
class Solution(object):
def maxDistance(self, grid):
result = 0
queue = deque([])
for row in range(len(grid)):
for col in range(len(grid[row])):
if grid[row][col] == 1:
queue.append((row,col))
if len(queue) == 0 or len(queue) == len(grid)*len(grid[0]):
return -1
while queue:
print(queue)
result += 1
for k in range(len(queue)):
i,j = queue.popleft()
for newI, newJ in [(i+1,j),(i-1,j),(i,j+1),(i,j-1)]:
if 0<= newI <len(grid) and 0<= newJ < len(grid[0]):
if grid[newI][newJ] == 0:
queue.append((newI,newJ))
grid[newI][newJ] = '*'
return result-1
~~~
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
if not grid or not grid[0]:
return -1
m, n = len(grid), len(grid[0])
q = collections.deque()
for i in range(m):
for j in range(n):
if grid[i][j] == 1:
q.append((i, j))
if len(q) == 0 or len(q) == m * n:
return -1
level = 1
result = -1
while q:
for _ in range(len(q)):
x, y = q.popleft()
for delta_x, delta_y in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
next_x = x + delta_x
next_y = y + delta_y
if next_x < 0 or next_x >= m or next_y < 0 or next_y >= n:
continue
if grid[next_x][next_y] == 0:
result = max(result, level)
q.append((next_x, next_y))
grid[next_x][next_y] = 1
level += 1
return result
只从陆地往外搜,并把本格标记为搜索过
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
n = len(grid)
steps = -1
q = collections.deque([(i, j) for i in range(n) for j in range(n) if grid[i][j] == 1])
if len(q) == 0 or len(q) == n ** 2:
return steps
while len(q) > 0:
for _ in range(len(q)):
x, y = q.popleft()
for xi, yj in [(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)]:
if xi >= 0 and xi < n and yj >= 0 and yj < n and grid[xi][yj] == 0:
q.append((xi, yj))
grid[xi][yj] = -1
steps += 1
return steps
时间复杂度 :O(N*N)
空间复杂度:O(N*N)
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
m, n = len(grid), len(grid[0])
q = deque([(i, j) for i in range(m) for j in range(n) if grid[i][j] == 1])
if len(q) == m * n or len(q) == 0:
return -1
directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]
step = 0
while q:
size = len(q)
for _ in range(size):
i, j = q.popleft()
for x, y in directions:
dx, dy = x + i, y + j
if 0 <= dx < m and 0 <= dy < n and grid[dx][dy] == 0:
q.append((dx, dy))
grid[dx][dy] = 1
step += 1
return step - 1
time complexity: O(mn) space complexity: O(mn)
C++ Code:
class Solution {
public:
int maxDistance(vector<vector<int>>& grid) {
/// min distance. Using bfs.
int row =grid.size();
int col = grid[0].size();
queue<pair<int,int>> que;
for(int i=0; i< row; i++)
{
for(int j =0; j < col; j++)
{
if(grid[i][j]==1)
{
que.push(make_pair(i, j));
}
}
}
vector<int> direction={-1,0,1,0,-1};
int ret = -1;
while(que.size())
{
pair<int,int> topNode = que.front();
que.pop();
int distance = grid[topNode.first][topNode.second];
for(int i = 0; i< direction.size()-1; i++)
{
int irow = topNode.first+direction[i];
int icol = topNode.second+direction[i+1];
if(irow<0||irow>=row||icol<0||icol>=col)
continue;
if(grid[irow][icol]!=0)
continue;
que.push(make_pair(irow,icol));
grid[irow][icol] = distance+1;
ret = max(ret, distance+1);
}
}
return ret==-1? ret: ret-1;
}
};
两种方法,bfs和dp;
dp方法:
dp[i][j] = 1 + min((dp[i-1][j], dp[i][j-1]), 1 + min(dp[i+1][j], dp[i][j+1]))
最后的结果是max(dp)
class Solution:
def maxDistance(self, g: List[List[int]]) -> int:
n = len(g)
dp = [[float('inf')] * n for i in range(n)]
for i in range(n):
for j in range(n):
if g[i][j] == 1:
dp[i][j] = 0
res = -float('inf')
for i in range(n):
for j in range(n):
if dp[i][j] != 0:
up = dp[i-1][j] if i-1 >= 0 else float('inf')
left = dp[i][j-1] if j-1 >= 0 else float('inf')
dp[i][j] = 1 + min(up, left)
for i in range(n-1, -1, -1):
for j in range(n-1, -1, -1):
if dp[i][j] != 0:
right = dp[i][j+1] if j+1 < n else float('inf')
down = dp[i+1][j] if i+1 < n else float('inf')
cur = 1 + min(right, down)
dp[i][j] = min(cur, dp[i][j])
res = max(res, dp[i][j])
if res not in (float('inf'), -float('inf')):
return res
return -1
Time: 遍历的三次矩阵,所以复杂度是O(n^2)
Space: dp矩阵 O(n^2)
BFS方法
先把所有的1入队列,然后不断扩展;不必使用visited数组,使用原始矩阵辅助即可:
class Solution:
def maxDistance(self, g: List[List[int]]) -> int:
n = len(g)
q = []
for i in range(n):
for j in range(n):
if g[i][j] == 1:
g[i][j] == -1
q.append((i, j))
if len(q) == 0 or len(q) == n * n:
return -1
dis = 0
while q:
size = len(q)
for i in range(size):
x, y = q.pop(0)
for dx, dy in [[-1,0], [1,0], [0,1], [0,-1]]:
xx = x + dx
yy = y + dy
if n > xx >= 0 and n > yy >= 0 and g[xx][yy] != -1:
q.append((xx, yy))
g[xx][yy] = -1
dis += 1
return dis - 1
Time: 每个点访问一遍,O(n^2)
Space: q最大是n^2,所以复杂度是 O(n^2)
https://leetcode-cn.com/problems/as-far-from-land-as-possible/
你现在手里有一份大小为 N x N 的 网格 grid,上面的每个 单元格 都用 0 和 1 标记好了。其中 0 代表海洋,1 代表陆地,请你找出一个海洋单元格,这个海洋单元格到离它最近的陆地单元格的距离是最大的。
我们这里说的距离是「曼哈顿距离」( Manhattan Distance):(x0, y0) 和 (x1, y1) 这两个单元格之间的距离是 |x0 - x1| + |y0 - y1| 。
如果网格上只有陆地或者海洋,请返回 -1。
示例 1:
输入:[[1,0,1],[0,0,0],[1,0,1]]
输出:2
解释:
海洋单元格 (1, 1) 和所有陆地单元格之间的距离都达到最大,最大距离为 2。
示例 2:
输入:[[1,0,0],[0,0,0],[0,0,0]]
输出:4
解释:
海洋单元格 (2, 2) 和所有陆地单元格之间的距离都达到最大,最大距离为 4。
提示:
1 <= grid.length == grid[0].length <= 100
grid[i][j] 不是 0 就是 1
Java Code:
class Solution {
private int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
public int maxDistance(int[][] grid) {
if (grid == null || grid.length == 0) {
return -1;
}
int row = grid.length;
int col = grid[0].length;
// 记录0到最近的1的距离
int[][] distance = new int[row][col];
Queue<int[]> queue = new LinkedList<>();
for (int r = 0; r < row; r++) {
for (int c = 0; c < col; c++) {
if (grid[r][c] == 1) {
for (int[] dir : directions) {
int x = r + dir[0];
int y = c + dir[1];
if (x < 0 || x >= row || y < 0 || y >= row || grid[x][y] == 1 || distance[x][y] != 0) {
continue;
}
distance[x][y] = 1;
queue.offer(new int[]{x, y});
}
}
}
}
while (!queue.isEmpty()) {
int[] cur = queue.poll();
int r = cur[0];
int c = cur[1];
for (int[] dir : directions) {
int x = r + dir[0];
int y = c + dir[1];
if (x < 0 || x >= row || y < 0 || y >= col || grid[x][y] == 1 || distance[x][y] != 0) {
continue;
}
distance[x][y] = distance[r][c] + 1;
queue.offer(new int[]{x, y});
}
}
int max = -1;
for (int r = 0; r < row; r++) {
for (int c = 0; c < col; c++) {
if (grid[r][c] == 0) {
max = Math.max(max, distance[r][c]);
}
}
}
return max == 0? -1 : max;
}
}
复杂度分析
令 n 为数组长度。
from collections import deque
from typing import List
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
'''
Q: 遍历全部海洋区域,找到某个海洋区域点,离 最近陆地 的距离是最大的
1. 找到所有陆地的点
2. 遍历陆地的点,每一圈陆地边上的海洋都标记为同一层
3. 离所有陆地最远的一层海洋,就满足题目要求
4. 一共能循环的层数,就是答案
'''
m = len(grid)
n = len(grid[0])
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
q = deque([(i, j) for j in range(n) for i in range(m) if grid[i][j] == 1])
# If no land or water exists in the grid, return -1.
if len(q) == m*n or len(q) == 0:
return -1
level = 0
while q:
size = len(q)
for _ in range(size):
i, j = q.popleft()
for x, y in directions:
xi, yj = x+i, y+j
if 0 <= xi < m and 0 <= yj < n and grid[xi][yj] == 0:
q.append((xi, yj))
grid[xi][yj] = 1
level += 1
return level - 1
# put every land cell into a queue
# do bfs
# update water cell distance to its nearest land
# update max distance
# time: O(m * n)
# space: O(m * n)
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
rows = len(grid)
cols = len(grid[0])
queue = []
for i in range(rows):
for j in range(cols):
if grid[i][j] == 1:
queue.append((i, j))
distance = 0
res = -1
# no water or no land
if len(queue) == rows * cols or not queue:
return res
while queue:
distance += 1
curr_size = len(queue)
for i in range(curr_size):
x, y = queue.pop(0)
for dx, dy in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
new_x = x + dx
new_y = y + dy
if new_x < 0 or new_x > rows - 1 or new_y < 0 or new_y > cols - 1:
continue
if grid[new_x][new_y] == 0:
queue.append((new_x, new_y))
grid[new_x][new_y] = distance
res = max(res, distance)
return res
模版题
class Solution {
private static final int[][] ds = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
public int maxDistance(int[][] grid) {
int m = grid.length, n = grid[0].length;
Queue<Pair> q = new LinkedList<>();
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 1) {
q.offer(new Pair(i, j));
}
}
}
if (q.size() == 0 || q.size() == m * n) return -1;
int level = 0;
while (!q.isEmpty()) {
int size = q.size();
for (int i = 0; i < size; i++) {
Pair p = q.poll();
for (int[] d : ds) {
int nx = p.x + d[0], ny = p.y + d[1];
if (nx >= 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] == 0) {
grid[nx][ny] = 1;
q.offer(new Pair(nx, ny));
}
}
}
level++;
}
return level - 1;
}
private class Pair {
int x, y;
Pair(int x, int y) {
this.x = x;
this.y = y;
}
}
}
思路:
该题目可以考虑使用BFS来做。
方法: BFS 广度优先
以陆地为起点,向四周扩散,每次向四周扩散一格。直到扩散到最后一个海洋,则到达该海洋的的距离即为最大的曼哈顿距离。
代码:
实现语言: C++
class Solution {
public:
int maxDistance(vector<vector
复杂度分析
时间复杂度: O(n^2) 空间复杂度: O(n^2)
BFS。
class Solution {
public:
vector<int> dx = {0, 1, 0, -1};
vector<int> dy = {1, 0, -1, 0};
int maxDistance(vector<vector<int>>& grid) {
queue<pair<int, int>> q;
vector<vector<int>> dist(grid.size(), vector(grid.size(), 1000));
for (int i = 0; i < grid.size(); i++) {
for (int j = 0; j < grid.size(); j++) {
if (grid[i][j] == 1) {
q.push({i, j});
dist[i][j] = 0;
}
}
}
while (!q.empty()) {
pair<int, int> top = q.front();
q.pop();
for (int i = 0; i < 4; i++) {
int newX = top.first + dx[i], newY = top.second + dy[i];
if (newX < 0 || newX >= grid.size() || newY < 0 || newY >= grid.size()) continue;
if (dist[newX][newY] > dist[top.first][top.second] + 1) {
dist[newX][newY] = dist[top.first][top.second] + 1;
q.push({newX, newY});
}
}
}
int res = -1;
for (int i = 0; i < grid.size(); i++) {
for (int j = 0; j < grid.size(); j++) {
if (grid[i][j] == 0 && dist[i][j] <= 200) res = max(res, dist[i][j]);
}
}
return res;
}
};
https://leetcode-cn.com/problems/as-far-from-land-as-possible/
BFS + 使用二维数组记录
class Solution {
public int maxDistance(int[][] grid) {
int m = grid.length;
int n = grid[0].length;
int[][] dists = new int[m][n];
for(int i = 0; i < m; i++) {
Arrays.fill(dists[i], Integer.MAX_VALUE);
}
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
if(grid[i][j] == 1) {
dists[i][j] = 0;
bfs(i, j, grid, dists);
}
}
}
int res = 0;
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
if(grid[i][j] == 0) res = Math.max(dists[i][j], res);
}
}
if(res == Integer.MAX_VALUE || res == 0) return -1;
return res;
}
private void bfs(int a, int b, int[][] grid, int[][] dists) {
int m = grid.length;
int n = grid[0].length;
Queue<int[]> queue = new LinkedList<>();
int[][] visited = new int[m][n];
queue.offer(new int[]{a, b});
visited[a][b] = 1;
while(!queue.isEmpty()) {
int[] cur = queue.poll();
int x = cur[0], y = cur[1];
int dist = dists[x][y] + 1;
if(x - 1 >= 0 && grid[x - 1][y] == 0 && visited[x - 1][y] == 0) {
dists[x - 1][y] = Math.min(dists[x - 1][y], dist);
visited[x - 1][y] = 1;
queue.offer(new int[]{x - 1, y});
}
if(x + 1 < m && grid[x + 1][y] == 0 && visited[x + 1][y] == 0) {
dists[x + 1][y] = Math.min(dists[x + 1][y], dist);
visited[x + 1][y] = 1;
queue.offer(new int[]{x + 1, y});
}
if(y - 1 >= 0 && grid[x][y - 1] == 0 && visited[x][y - 1] == 0) {
dists[x][y - 1] = Math.min(dists[x][y - 1], dist);
visited[x][y - 1] = 1;
queue.offer(new int[]{x, y - 1});
}
if(y + 1 < n && grid[x][y + 1] == 0 && visited[x][y + 1] == 0) {
dists[x][y + 1] = Math.min(dists[x][y + 1], dist);
visited[x][y + 1] = 1;
queue.offer(new int[]{x, y + 1});
}
}
}
}
O(n ^ 2)
O(n ^ 2)
多源BFS,并且要记层数。
class Solution {
public int maxDistance(int[][] grid) {
int m = grid.length;
int n = grid[0].length;
Queue<int[]> q = new LinkedList<>();
for (int i=0; i<m; i++) {
for (int j=0; j<n; j++) {
if (grid[i][j] == 1) {
q.offer(new int[]{i, j});
}
}
}
int[] dx = new int[] {1, 0, -1, 0};
int[] dy = new int[] {0, 1, 0, -1};
int step = -1;
boolean foundWater = false;
while (!q.isEmpty()) {
step++;
int size = q.size();
for (int i=0; i<size; i++) {
int[] rowcol = q.poll();
for (int k=0; k<4; k++) {
int newRow = rowcol[0] + dx[k];
int newCol = rowcol[1] + dy[k];
if (newRow >= 0 && newRow < m && newCol >= 0 && newCol < n && grid[newRow][newCol] == 0) {
grid[newRow][newCol] = 2;
foundWater = true;
q.offer(new int[]{newRow, newCol});
}
}
}
}
return foundWater ? step : -1;
}
}
TC: O(m * n) SC: O(min(m, n))
https://leetcode.com/problems/as-far-from-land-as-possible/
const maxDistance = function (grid) {
let queue = [],
steps = 0,
col = grid[0].length,
row = grid.length,
dirs = [
[0, 1],
[1, 0],
[-1, 0],
[0, -1],
];
for (let i = 0; i < row; i++)
for (let j = 0; j < col; j++) if (grid[i][j]) queue.push([i, j, 0]);
while (queue.length) {
steps++;
const len = queue.length;
for (let i = 0; i < len; i++) {
const [x, y, dis] = queue.shift();
for (const [xSteps, ySteps] of dirs) {
if (grid[x + xSteps] && grid[x + xSteps][y + ySteps] === 0) {
queue.push([x + xSteps, y + ySteps, dis + 1]);
grid[x + xSteps][y + ySteps] = -1;
}
}
}
}
return steps <= 1 ? -1 : steps - 1;
};
从所有的陆地开始, 先将陆地添加入栈中
每次 visit queue 中元素的 neighbour, 然后 step += 1, 每一次 访问结束代表 queue 中的元素访问时 需要 从 某一处陆地走 step 步才能达到
访问海洋后, 进行标记, 并且将海洋的未被访问的 neighbour 添加入 queue 中进行下一轮访问
最后 返回 step, step 的大小是最后一轮能被访问到的海洋需要的步数的大小, 利用了 BFS 每次遍历最接近的一层的特性
from collections import deque
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
m, n = len(grid), len(grid[0])
directions = [(1,0), (0,1), (-1,0), (0,-1)]
step = -1
q = deque()
for i in range(m):
for j in range(n):
if grid[i][j] == 1:
q.append((i,j))
# special case of no land or no water
if len(q) == m*n or len(q) == 0:
return -1
while len(q) > 0:
for _ in range(len(q)):
i, j = q.popleft()
for d1, d2 in directions:
i1, j1 = i+d1, j+d2
if i1 < 0 or i1 >= m or j1 < 0 or j1 >= n:
continue
if grid[i1][j1] != 0:
continue
q.append((i1, j1))
grid[i1][j1] = 1
step += 1
return step
m,n 为 行 和 列 的数目
时间复杂度: O(mn) 每个节点都被访问一次
空间复杂度: O(mn) queue 的空间复杂度是 O(mn)
BFS. The problem can be converted to finding the root whose minimum weighted edge to its nodes is maximum. The root is the cell with water, its nodes are the cells of land it can access to. The edge's weight is the Manhattan distance between the water cell and land cell. Then this is a graph problem, which can have multiple roots. For problems of searching minimum in maximum or maximum in minimum, BFS is better than DFS, since you can expand the search range a layer by a layer, from the center to the most out layer.
from collections import deque
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
stack = deque()
seen = set()
n = len(grid)
if n < 1:
return -1
m = len(grid[0])
if m < 1:
return -1
ans = -1
for i in range(n):
for j in range(m):
if grid[i][j] == 1:
seen.add((i, j))
stack.append([i, j, 0])
if len(stack) == 0 or len(stack) == m * n:
return -1
while stack:
l = len(stack)
for _ in range(l):
i, j, c = stack.popleft()
for h in {(-1, 0), (0, 1), (0, -1), (1,0)}:
ii, jj = i + h[0], j + h[1]
if 0 <= ii < n and 0 <= jj < m and (ii, jj) not in seen:
seen.add((ii, jj))
ans = max(ans, c + 1)
stack.append([ii, jj, c + 1])
return ans
Time: O(N^2). You need to search all cells. Space: O(N^2). You need to store all cells in seen and stack.
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
n = len(grid)
queue = deque()
res = 0
for i in range(n):
for j in range(n):
if grid[i][j] == 1:
queue.append([(i,j), 0])
while queue:
for _ in range(len(queue)):
t = queue.popleft()
r, c = t[0]
d = t[1]
res = max(res, d)
for dr, dc in [(1,0), (-1,0), (0,1), (0,-1)]:
x = r+dr
y = c+dc
if (x<0 or x==n) or (y<0 or y==n):
continue
if grid[x][y] == 0:
grid[x][y] = -1
queue.append([(x,y), d+1])
if res == 0:
res = -1
return res
Space: O(n^2)
Time: O(n^2)
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
n = len(grid)
steps = -1
queue = collections.deque([(i, j) for i in range(n) for j in range(n) if grid[i][j] == 1])
if len(queue) == 0 or len(queue) == n ** 2: return steps
while len(queue) > 0:
for _ in range(len(queue)):
x, y = queue.popleft(0)
for xi, yj in [(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)]:
if xi >= 0 and xi < n and yj >= 0 and yj < n and grid[xi][yj] == 0:
queue.append((xi, yj))
grid[xi][yj] = -1
steps += 1
return steps
遍历地图,以每一个水域cell为中心,用 bfs 找到离它最近的岛屿的距离,记录最大距离
class Solution {
public int maxDistance(int[][] grid) {
int res = -1;
for (int row = 0; row < grid.length; row++) {
for (int col = 0; col < grid.length; col++) {
if (grid[row][col] == 0) {
res = Math.max(res, distanceToIsland(grid, row, col));
}
}
}
return res;
}
private int distanceToIsland(int[][] grid, int row, int col) {
boolean[][] visited = new boolean[grid.length][grid.length];
int[] drow = {0, 0, 1, -1};
int[] dcol = {1, -1, 0, 0};
Queue<int[]> queue = new LinkedList<>();
queue.offer(new int[]{row, col, 0});
visited[row][col] = true;
while (!queue.isEmpty()) {
int[] curPosition = queue.poll();
for(int i = 0; i < 4; i++) {
int newRow = curPosition[0] + drow[i];
int newCol = curPosition[1] + dcol[i];
if (!(newRow >= 0 && newRow < grid.length && newCol >= 0 && newCol < grid.length)){
continue;
}
if (!visited[newRow][newCol]) {
queue.offer(new int[]{newRow, newCol, curPosition[2] + 1});
visited[newRow][newCol] = true;
if (grid[newRow][newCol] == 1) {
return curPosition[2] + 1;
}
}
}
}
return -1;
}
}
时间: O(n^4) \ 空间: O(n^2)
class Solution {
int[][] directions = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
public int maxDistance(int[][] grid) {
Queue<Point> queue = new LinkedList();
int m = grid.length, n = grid[0].length;
int[][] visited = new int[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 1) {
queue.add(new Point(i, j));
visited[i][j] = 1;
}
}
}
int res = -1;
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
Point curP = queue.poll();
for (int[] d : directions) {
int nX = curP.x + d[0];
int nY = curP.y + d[1];
if (nX >= 0 && nX < m && nY >= 0 && nY < n && grid[nX][nY] == 0 && visited[nX][nY] == 0) {
queue.add(new Point(nX, nY));
visited[nX][nY] = 1;
}
}
}
res++;
}
return res == 0 ? -1 : res;
}
private static class Point {
int x;
int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
}
时间 O(n) 每个点进出queue一次
空间 O(n)
python
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
m, n = len(grid), len(grid[0])
steps = -1
queue = [[i, j] for i in range(m) for j in range(n) if grid[i][j] == 1]
if len(queue) == 0 or len(queue) == m * n:
return steps
while queue:
for _ in range(len(queue)):
x, y = queue.pop(0)
for xi, yj in [(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)]:
if xi >= 0 and xi < n and yj >= 0 and yj < n and grid[xi][yj] == 0:
queue.append([xi, yj])
grid[xi][yj] = -1
steps += 1
return steps
class Solution {
public int maxDistance(int[][] grid) {
Deque<int[]> queue = new LinkedList<>();
int N = grid.length;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (grid[i][j] == 1) {
queue.add(new int[]{i, j});
}
}
}
int[] dx = {0, 0, 1, -1};
int[] dy = {1, -1, 0, 0};
boolean hasOcean = false;
int[] points = null;
// 开始从每个点bfs
while (!queue.isEmpty()) {
points = queue.poll();
for (int i = 0; i < 4; i++) {
int x = points[0] + dx[i];
int y = points[1] + dy[i];
if (x < 0 || y < 0 || x >= N || y >= N || grid[x][y] != 0) {
continue;
}
hasOcean = true;
grid[x][y] = grid[points[0]][points[1]] + 1;
queue.add(new int[]{x, y});
}
}
if (!hasOcean || points == null) {
return -1;
}
return grid[points[0]][points[1]] - 1;
}
}
bfs
class Solution {
private:
struct pos{
int x;
int y;
pos(int X,int Y):x(X),y(Y){}
};
int xd[4]={0,1,0,-1};
int yd[4]={1,0,-1,0};
vector<vector<bool>>visit;
public:
int maxDistance(vector<vector<int>>& grid) {
if(check(grid))
return -1;
int res=-1;
for(int i=0;i<grid.size();++i){
for(int j=0;j<grid[0].size();++j){
if(grid[i][j]==0){
int t=bfs(grid,i,j);
res=res>t?res:t;
}
}
}
return res;
}
bool check(vector<vector<int>>& grid){
int one=0,zero=0;
for(auto x:grid){
for(auto y:x){
if(zero&&one)
return false;
if(y==1)one++;
if(y==0)zero++;
}
}
return true;
}
int bfs(vector<vector<int>> grid,int x,int y){
int size=grid.size();
visit=vector<vector<bool>>(size,vector<bool>(size,false));
queue<pos*>q;
q.push(new pos(x,y));
while(!q.empty()){
int frontX=q.front()->x;
int frontY=q.front()->y;
q.pop();
visit[frontX][frontY]=1;
if(grid[frontX][frontY]==1){
return abs(x-frontX)+abs(y-frontY);
}
for(int i=0;i<4;i++){
int newX=frontX+xd[i];
int newY=frontY+yd[i];
if(newX>=0&&newY>=0&&newX<size&&newY<size&&!visit[newX][newY]){
q.push(new pos(newX,newY));
}
}
}
return -1;
}
};
复杂度分析
class Solution
{
public:
int maxDistance(vector<vector<int>> &grid)
{
// find the maximum depth away from the land vertices
// use all land as starting vertices and expand from them
std::queue<std::pair<int, int>> aQueue;
int n = grid.size();
for (int jj = 0; jj < n; jj++) {
for (int ii = 0; ii < n; ii++) {
if (grid[jj][ii] == 0) continue;
aQueue.push({ jj, ii });
}
}
// pruning
if (aQueue.size() == 0 || aQueue.size() == n * n) return -1;
std::vector<std::pair<int, int>> dirs{ { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };
int depth{ 0 };
while (!aQueue.empty()) {
int nsize = aQueue.size();
depth++;
for (int ii = 0; ii < nsize; ii++) {
auto me = aQueue.front();
aQueue.pop();
// grid[me.first][me.second] = depth;
for (auto &dir : dirs) {
int row = me.first + dir.first;
int col = me.second + dir.second;
if (row < 0 || row >= n || col < 0 || col >= n || grid[row][col] != 0) continue;
// Set the neigboring depth here to avoid adding the same neighbors from different vertices
grid[row][col] = depth;
aQueue.emplace(row, col);
}
}
}
return depth - 1;
}
};
1162. 地图分析
https://leetcode-cn.com/problems/as-far-from-land-as-possible/
参考题解
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
n = len(grid)
queue = collections.deque([(i, j) for i in range(n) for j in range(n) if grid[i][j]])
if len(queue) == 0 or len(queue) == n * n:
return -1
distance = -1
while queue:
distance += 1
for _ in range(len(queue)):
x, y = queue.popleft()
for dx, dy in ((1, 0), (-1, 0), (0, 1), (0, -1)):
nx, ny = x + dx, y + dy
if 0 <= nx < n and 0 <= ny < n and not grid[nx][ny]:
grid[nx][ny] = 1
queue.append((nx, ny))
return distance
var maxDistance = function (grid) {
if (grid.length < 2) return -1;
let n = grid.length;
// 创建 dp 状态矩阵
let dp = new Array(n);
for (let i = 0; i < n; i++) {
dp[i] = new Array(n);
}
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
dp[i][j] = grid[i][j] ? 0 : Infinity;
}
}
// 从左上向右下遍历
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
if (grid[i][j]) continue;
if (i - 1 >= 0) dp[i][j] = Math.min(dp[i][j], dp[i - 1][j] + 1);
if (j - 1 >= 0) dp[i][j] = Math.min(dp[i][j], dp[i][j - 1] + 1);
}
}
// 从右下向左上遍历
for (let i = n - 1; i >= 0; i--) {
for (let j = n - 1; j >= 0; j--) {
if (grid[i][j]) continue;
if (i + 1 < n) dp[i][j] = Math.min(dp[i][j], dp[i + 1][j] + 1);
if (j + 1 < n) dp[i][j] = Math.min(dp[i][j], dp[i][j + 1] + 1);
}
}
let ans = -1;
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
if (!grid[i][j]) ans = Math.max(ans, dp[i][j]);
}
}
if (ans === Infinity) {
return -1;
} else {
return ans;
}
};
https://leetcode-cn.com/problems/as-far-from-land-as-possible/
单源朴素BFS, 多源朴素BFS
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
# time row * col * (row * col) = n**4
# space row * col
def bfs(x, y):
queue = deque()
visited = [[False for _ in range(col)] for _ in range(row)]
queue.append((x, y))
visited[x][y] = True
step = 1
while(queue):
size = len(queue)
for _ in range(size):
x, y = queue.popleft()
for new_x, new_y in [(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)]:
if 0<=new_x<row and 0<=new_y<col and not visited[new_x][new_y]:
visited[new_x][new_y] = True
queue.append((new_x, new_y))
if grid[new_x][new_y] == 1:
return step
step += 1
return -1
row = len(grid)
col = len(grid[0])
maxStep = -1
for i in range(row):
for j in range(col):
if grid[i][j] == 0:
maxStep = max(maxStep, bfs(i, j))
return maxStep
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
# time n**2
# space n**2
# 朴素多源BFS
row = len(grid)
col = len(grid[0])
queue = collections.deque()
for i in range(row):
for j in range(col):
if grid[i][j] == 1:
queue.append((i, j))
# corner case
if len(queue) == 0 or len(queue) == row * col:
return -1
# 会多算一次 所以设置成-1 可能的解决方案:如果能写在方法里就可以提前return
distance = -1
while (queue):
size = len(queue)
for _ in range(size):
x, y = queue.popleft()
for newX, newY in [(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)]:
if 0<=newX<row and 0<=newY<col:
if grid[newX][newY] != 1:
grid[newX][newY] = 1
queue.append((newX, newY))
distance += 1
return distance
BFS
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
distance = 0
n = len(grid)
queue = collections.deque([])
for i in range(n):
for j in range(n):
if grid[i][j] == 1:
queue.append([i,j])
if len(queue) == 0 or len(queue) == n*n : return -1
while(queue):
distance+=1
for i in range(len(queue)):
t = queue.popleft()
for dir in [[0,1], [0,-1], [1,0], [-1,0]]:
x = t[0] + dir[0]
y = t[1] + dir[1]
if x<0 or x>=n or y<0 or y>=n or grid[x][y]!=0: continue
grid[x][y] = distance
queue.append([x,y])
return distance-1
Space: O(nn) Time: O(nn)
遍历 grid 每个为 0 的 postion,并对此 position 做 bfs 搜索,拿到离该 position 曼哈顿距离最近的 val 为 1 的距离数值标为 minPer0; 遍历每个 0 拿到的 minPer0 做比较并更新 maxDistance;
const int dx[] = {0, 0, -1, 1};
const int dy[] = {-1, 1, 0, 0};
int absVal(int a, int b) {
if (a < b)
return b - a;
return a - b;
}
int maxDistance(vector<vector<int>> grid) {
int maxDistance = 0;
int res[3] = {0};
int m = grid.size();
int n = grid[0].size();
int nx, ny;
int minPer0 = 0;
bool visited[m][n];
memset(visited, false, sizeof(visited));
memset(res, -1, sizeof(res));
queue<int> q;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (!grid[i][j]) {
memset(visited, false, sizeof(visited));
minPer0 = m + n;
visited[i][j] = true;
int idx = i * n + j;
q.push(idx);
while (!q.empty()) {
idx = q.front();
q.pop();
int x = idx / n;
int y = idx % n;
for (int k = 0; k < 4; ++k) {
nx = x + dx[k];
ny = y + dy[k];
if (nx >= 0 && nx < m && ny >= 0 && ny < n) {
if (grid[nx][ny])
minPer0 = min(minPer0, absVal(nx, i) + absVal(ny, j));
else if (!visited[nx][ny]) {
visited[nx][ny] = true;
idx = nx * n + ny;
q.push(idx);
}
}
}
}
if (minPer0 > maxDistance) {
maxDistance = minPer0;
res[0] = i;
res[1] = j;
res[2] = maxDistance;
}
}
}
}
// cout << "x:" << res[0] << endl;
// cout << "y:" << res[1] << endl;
// cout << "maxDistance:" << res[2] << endl;
return maxDistance;
}
思路: 这题和 count island 很像, 但是是bfs , 很好用的 queue, 每次延深一步即可. 另外我这个 helper 还是需要用的 最后, 时间空间复杂度都是 O(N)
from collections import deque
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
def search(grid,r,c):
res = []
for x,y in [(r-1,c),(r+1,c),(r,c-1),(r,c+1)]:
if x>= 0 and y >=0 and x <len(grid) and y< len(grid[0]) and grid[x][y] == 0:
res.append((x,y))
return res
#q = []
q = deque()
for r in range(len(grid)):
for c in range(len(grid[0])):
if grid[r][c] == 1:
q.append((r,c))
res = 0
while q:
x, y = q.popleft()
actions = search(grid,x, y)
if actions:
for temp_x, temp_y in actions:
grid[temp_x][temp_y] = grid[x][y] +1
res = max(res,grid[temp_x][temp_y])
q.append((temp_x,temp_y))
return res -1
import collections
class Solution(object):
def maxDistance(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
n = len(grid)
steps = -1
queue = collections.deque()
for i in range(n):
for j in range(n):
if grid[i][j] == 1:
queue.append((i, j))
# print(queue)
if len(queue) == 0 or len(queue) == n ** 2: return steps
while len(queue) > 0:
for _ in range(len(queue)):
x, y = queue.popleft()
for xi, yj in [(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)]:
if xi >= 0 and xi < n and yj >= 0 and yj < n and grid[xi][yj] == 0:
queue.append((xi, yj))
grid[xi][yj] = -1
steps += 1
return steps
时间复杂度:O(N^2) 空间复杂度:O(N^2)
calculate distance -- BFS
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
#calculate distance, use BFS
#put all 1s to queue at the same time, and then start to do BFS for each 1
n = len(grid)
ans = -1
queue = collections.deque()
DIR = [0, 1, 0, -1, 0]
for i in range(n):
for j in range(n):
if grid[i][j] == 1:
queue.append((i, j))
if len(queue) == 0 or len(queue) == n ** 2:
return ans
while queue:
ans += 1
for _ in range(len(queue)):
r, c = queue.popleft()
for i in range(4):
xr = r + DIR[i]
xc = c + DIR[i+1]
if xr >= 0 and xr < n and xc >= 0 and xc < n and grid[xr][xc] == 0:
queue.append((xr, xc))
grid[xr][xc] = -1
#ans += 1
return ans
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
n = len(grid)
queue = collections.deque([(i, j) for i in range(n) for j in range(n) if grid[i][j]])
if len(queue) == 0 or len(queue) == n * n:
return -1
distance = -1
while queue:
distance += 1
for _ in range(len(queue)):
x, y = queue.popleft()
for dx, dy in ((1, 0), (-1, 0), (0, 1), (0, -1)):
nx, ny = x + dx, y + dy
if 0 <= nx < n and 0 <= ny < n and not grid[nx][ny]:
grid[nx][ny] = 1
queue.append((nx, ny))
return distance
https://leetcode.com/problems/as-far-from-land-as-possible/
Start from all islands and do BFS till reach all grid.
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
r_len, c_len = len(grid), len(grid[0])
q = deque([(r, c) for r in range(r_len) for c in range(c_len) if grid[r][c] == 1])
dist = -1
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
visited = set(q)
while q:
size = len(q)
dist += 1
for _ in range(size):
cur_r, cur_c = q.popleft()
for d in directions:
new_r, new_c = cur_r + d[0], cur_c + d[1]
if 0 <= new_r < len(grid) and 0 <= new_c < len(grid[0]):
if (new_r, new_c) in visited:
continue
else:
visited.add((new_r, new_c))
q.append((new_r, new_c))
return -1 if dist == 0 else dist
时间复杂度: O(RC) 空间复杂度:O(RC)
Go Code:
func maxDistance(grid [][]int) int {
var q [][2]int
N := len(grid)
for i := 0; i < N; i++ {
for j := 0; j < N; j++ {
if grid[i][j] == 1 {
q = append(q, [2]int{i, j})
}
}
}
if len(q) == 0 || len(q) == N*N {
return -1
}
res := -1
for len(q) > 0 {
size := len(q)
for i := 0; i < size; i++ {
x, y := q[i][0], q[i][1]
for _, dir := range [][]int{{0, 1}, {0, -1}, {1, 0}, {-1, 0}} {
nx, ny := x+dir[0], y+dir[1]
// 检查边界
if !(nx >= 0 && nx < N && ny >= 0 && ny < N) {
continue
}
// 判断是否之前走过
if grid[nx][ny] > 0 {
continue
}
grid[nx][ny] = grid[x][y] + 1
// 加入队列
q = append(q, [2]int{nx, ny})
}
}
q = q[size:]
res++
}
return res
}
复杂度分析
令 n 为数组长度。
class Solution {
public int maxDistance(int[][] grid) {
Queue<int[]> queue = new LinkedList<>();
// 遍历所有的陆地
for (int row = 0; row < grid.length; row ++) {
for (int col = 0; col < grid[0].length; col ++) {
if (grid[row][col] == 1) {
queue.offer(new int[]{row, col});
}
}
}
int[][] dirs = new int[][] {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
int level = 0;
if (queue.isEmpty() || queue.size() == grid.length * grid[0].length) return -1;
while (!queue.isEmpty()) {
int cnt = queue.size();
for (int i = 0; i < cnt; i ++) {
int[] point = queue.poll();
for (int[] dir : dirs) {
int newX = point[0] + dir[0];
int newY = point[1] + dir[1];
if (isValid(grid, newX, newY)) {
grid[newX][newY] = 1;
queue.offer(new int[] {newX, newY});
}
}
}
level ++;
}
// 填到最后一个海水时,它也会遍历周围的海,所以返回的结果需要 - 1
return level - 1;
}
public boolean isValid(int grid[][], int r, int c) {
return r >= 0 && r < grid.length && c >= 0 && c < grid[0].length && grid[r][c] == 0;
}
} 复杂度: Time: O(N ^ 2) Space: O(N ^ 2)
class Solution: def maxDistance(self, grid: List[List[int]]) -> int: N = len(grid)
queue = []
# 将所有的陆地格子加入队列
for i in range(N):
for j in range(N):
if grid[i][j] == 1:
queue.append((i, j))
# 如果我们的地图上只有陆地或者海洋,请返回 -1。
if len(queue) == 0 or len(queue) == N * N:
return -1
distance = -1
while len(queue) > 0:
distance += 1
# 这里一口气取出 n 个结点,以实现层序遍历
n = len(queue)
for i in range(n):
r, c = queue.pop(0)
# 遍历上边单元格
if r-1 >= 0 and grid[r-1][c] == 0:
grid[r-1][c] = 2
queue.append((r-1, c))
# 遍历下边单元格
if r+1 < N and grid[r+1][c] == 0:
grid[r+1][c] = 2
queue.append((r+1, c))
# 遍历左边单元格
if c-1 >= 0 and grid[r][c-1] == 0:
grid[r][c-1] = 2
queue.append((r, c-1))
# 遍历右边单元格
if c+1 < N and grid[r][c+1] == 0:
grid[r][c+1] = 2
queue.append((r, c+1))
return distance
class Solution {
public:
static constexpr int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
static constexpr int MAX_N = 100 + 5;
struct Coordinate {
int x, y, step;
};
int n, m;
vector<vector<int>> a;
bool vis[MAX_N][MAX_N];
int findNearestLand(int x, int y) {
memset(vis, 0, sizeof vis);
queue <Coordinate> q;
q.push({x, y, 0});
vis[x][y] = 1;
while (!q.empty()) {
auto f = q.front(); q.pop();
for (int i = 0; i < 4; ++i) {
int nx = f.x + dx[i], ny = f.y + dy[i];
if (!(nx >= 0 && nx <= n - 1 && ny >= 0 && ny <= m - 1)) {
continue;
}
if (!vis[nx][ny]) {
q.push({nx, ny, f.step + 1});
vis[nx][ny] = 1;
if (a[nx][ny]) {
return f.step + 1;
}
}
}
}
return -1;
}
int maxDistance(vector<vector<int>>& grid) {
this->n = grid.size();
this->m = grid.at(0).size();
a = grid;
int ans = -1;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (!a[i][j]) {
ans = max(ans, findNearestLand(i, j));
}
}
}
return ans;
}
};
问题为离陆地最远的海洋。把所有陆地加入queue中,找到陆地相邻的所有海洋加入queue中,直到没有合适的海洋加入,也就是找最远的海洋层。
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
queue = collections.deque([])
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == 1:
queue.append((i, j))
if len(queue) == 0 or len(queue) == len(grid) * len(grid):
return -1
step = -1
while queue:
for _ in range(len(queue)):
x, y = queue.popleft()
for x1, y1 in [(1, 0), (-1, 0), (0, 1), (0, -1)]:
if x + x1 >= 0 and x + x1 <= len(grid) - 1 and y + y1 >= 0 and y + y1 <= len(grid) - 1 and grid[x + x1][y + y1] == 0:
queue.append((x + x1, y + y1))
grid[x + x1][y + y1] = -1
step += 1
return step
时间复杂度:O(n2) 空间复杂度:O(n2)
找到所有的陆地,从陆地开始BFS,层次遍历,知道所有的海洋都被搜索。
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
dx = [1,0,-1,0]
dy = [0,1,0,-1]
queue_one = collections.deque()
row = len(grid)
col = len(grid[0])
for r in range(row):
for c in range(col):
if grid[r][c] == 1:
queue_one.append((r,c))
n = len(queue_one)
if n==0 or n == row*col:
return -1
seen = set()
ans = -1
while queue_one:
n = len(queue_one)
ans+=1
for _ in range(n):
x,y = queue_one.popleft()
for i in range(4):
nx,ny = x+dx[i],y+dy[i]
if 0<=nx<row and 0<=ny<col and (nx,ny) not in seen and grid[nx][ny] == 0:
seen.add((nx,ny))
queue_one.append((nx,ny))
return ans
复杂度分析
class Solution {
int[][] moves = new int[][]{{1,0},{-1,0},{0,1},{0,-1}};
public int maxDistance(int[][] grid) {
int cells = grid.length * grid[0].length;
for(int[] gr : grid)
for(int g : gr)if(g==1)cells--;
if(cells==grid.length * grid[0].length || cells==0)return -1;
int it = 1;
while(cells>0){
for(int r = 0;r<grid.length;r++){
for(int c=0;c<grid[r].length;c++){
if(grid[r][c] == it){
for(int[] move : moves){
int rT = r+move[0];
int cT = c+move[1];
if(rT<0 || cT<0 ||rT==grid.length||cT==grid[rT].length || grid[rT][cT]!=0)continue;
grid[rT][cT]=it+1;
cells--;
}
}
}
}
it++;
}
return it-1;
}
}
class Solution {
public int maxDistance(int[][] grid) {
Queue<int[]> queue = new LinkedList<>();
// 遍历所有的陆地
for (int row = 0; row < grid.length; row ++) {
for (int col = 0; col < grid[0].length; col ++) {
if (grid[row][col] == 1) {
queue.offer(new int[]{row, col});
}
}
}
int[][] dirs = new int[][] {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
int level = 0;
if (queue.isEmpty() || queue.size() == grid.length * grid[0].length) return -1;
while (!queue.isEmpty()) {
int cnt = queue.size();
for (int i = 0; i < cnt; i ++) {
int[] point = queue.poll();
for (int[] dir : dirs) {
int newX = point[0] + dir[0];
int newY = point[1] + dir[1];
if (isValid(grid, newX, newY)) {
grid[newX][newY] = 1;
queue.offer(new int[] {newX, newY});
}
}
}
level ++;
}
// 填到最后一个海水时,它也会遍历周围的海,所以返回的结果需要 - 1
return level - 1;
}
public boolean isValid(int grid[][], int r, int c) {
return r >= 0 && r < grid.length && c >= 0 && c < grid[0].length && grid[r][c] == 0;
}
}
时间复杂度:O(N^2),其中 N 为数组长度。 空间复杂度:O(N^2)
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
if not grid: return
queue = []
row, col = len(grid), len(grid[0])
for i in range(row):
for j in range(col):
if grid[i][j] == 1:
queue.append((i, j, 0))
res = 0
d = [(0, 1), (0, -1), (1, 0), (-1, 0)]
while queue:
i, j, res = queue.pop(0)
for xd, yd in d:
x, y = i + xd, j + yd
if row > x >= 0 and col > y >= 0 and grid[x][y] == 0:
grid[x][y] = 1
queue.append((x, y, res + 1))
return res if res != 0 else -1
1162. 地图分析
入选理由
暂无
题目地址
https://leetcode-cn.com/problems/as-far-from-land-as-possible/
前置知识
暂无
题目描述