Open azl397985856 opened 2 years ago
多源BFS 的基本应用。将所有陆地都加入初始队列,BFS 遍历,然后将遇到的座标,都变成陆地,所有海洋都变陆地需要的轮数就是答案。
时间复杂度:O(mxn)
空间复杂度:O(mxn) 最坏情况下,所有点都是 1,那么都会加入队列。
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
row = len(grid)
col = len(grid[0])
q = []
for i in range(row):
for j in range(col):
if grid[i][j] == 1:
q.append((i, j))
q = deque(q)
cnt = 0
while q:
newq = []
flag = False
while q:
px, py = q.popleft()
for dx, dy in [(0, -1), (0, 1), (1, 0), (-1, 0)]:
x = px + dx
y = py + dy
if 0 <= x < row and 0 <= y < col and grid[x][y] != 1:
grid[x][y] = 1
newq.append((x, y))
flag = True
q = deque(newq)
if flag:
cnt += 1
return cnt if cnt > 0 else -1
思路 陆地找海洋,从所有陆地开始延伸找临近的海洋,一圈圈找直到所有格子被探索过,圈数就是最远距离
代码
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
n = len(grid)
land = []
res = -1
for x in range(n):
for y in range(n):
if grid[x][y] == 1:
land.append((x,y))
if len(land) == 0 or len(land) == n ** 2:
return res
while land:
for _ in range(len(land)):
x, y = land.pop(0)
for x1, y1 in [(x+1, y), (x-1, y), (x, y+1), (x, y-1)]:
if x1 >= 0 and x1 < n and y1 >= 0 and y1 < n and grid[x1][y1] == 0:
land.append((x1,y1))
grid[x1][y1] = -1
res += 1
return res
复杂度 时间 O(n^2) 空间 O(n^2)
# 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
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;
}
}
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
n = len(grid)
q = []
for i in range(n):
for j in range(n):
if grid[i][j] == 1:
q.append((i, j)) #陆地进队
#只有海洋/只有陆地,返回-1
if len(q) == 0 or len(q) == n**2:
return -1
steps = -1
while q:
n = len(q)
for _ in range(n):
row, col = q.pop(0)
for x, y in [(row + 1, col), (row - 1, col), (row, col - 1), (row, col+1)]:
if x >= 0 and x < len(grid) and y >= 0 and y < len(grid):
if grid[x][y] == 0:
q.append((x, y))
grid[x][y] = -1
steps += 1
return steps
BFS
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
ans = -1
stack = collections.deque()
seen = set()
m = len(grid)
if m < 1:
return -1
n = len(grid[0])
if n<1:
return -1
for i in range(m):
for j in range(n):
if grid[i][j] ==1 and (i, j) not in seen:
stack.append((i, j))
seen.add((i,j))
if len(seen) == 0 or len(seen) == m * n:
return -1
while stack:
l = len(stack)
for _ in range(l):
i, j = stack.popleft()
for d in {(0, -1), (0, 1), (1, 0), (-1,0)}:
mm, nn = i + d[0], j+d[1]
if 0<=mm<m and 0<=nn<n and (mm, nn) not in seen and grid[mm][nn] == 0:
stack.append((mm, nn))
seen.add((mm, nn))
ans += 1
return ans
Time: O(mn) Space: O(mn)
BFS
var maxDistance = function(grid) {
let n = grid.length
let queue = []
for(let i = 0; i < n; i++) {
for(let j = 0; j < n; j++) {
if(grid[i][j] == 1) {
queue.push([i, j])
}
}
}
let ans = -1
if(queue.length === 0 || queue.length === n * n) {
return ans
}
let locations = [[0, -1], [0, 1], [-1, 0], [1, 0]]
while (queue.length != 0) {
let len = queue.length
for (let k = 0; k < len; k++) {
let [x, y] = queue.shift()
for (let location of locations) {
let nextI = x + location[0]
let nextJ = y + location[1]
if (nextI >= 0 && nextI < n && nextJ >=0 && nextJ < n && grid[nextI][nextJ] == 0) {
grid[nextI][nextJ] = 1
queue.push([nextI, nextJ])
}
}
}
ans++
}
return ans
};
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
from collections import deque
q = deque([])
n = len(grid)
for row in range(n):
for col in range(n):
if grid[row][col] == 1:
q.append([row, col])
if not q:
return -1
full_land = True
dx = [-1,1,0,0]
dy = [0,0,-1,1]
while q:
coordinate = q.popleft()
row = coordinate[0]
col = coordinate[1]
for i in range(4):
newrow = row + dx[i]
newcol = col + dy[i]
if newrow < 0 or newrow > n - 1 or newcol < 0 or newcol > n - 1 or grid[newrow][newcol]:
continue
else:
full_land = False
grid[newrow][newcol] = grid[row][col] + 1
q.append([newrow,newcol])
if full_land:
return -1
return max([max(row) for row in grid]) - 1
time complexity: O(n^2) space complexity: 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()
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
复杂度分析
n, m = len(grid), len(grid[0])
dis = [[float("inf") for j in range(m+2)] for i in range(n+2)]
for i in range(1, n+1):
for j in range(1, m+1):
if grid[i-1][j-1]:
dis[i][j] = 0
else:
dis[i][j] = min(dis[i-1][j], dis[i][j-1]) + 1
res = -1
for i in range(n, 0, -1):
for j in range(m, 0, -1):
if grid[i-1][j-1]:
dis[i][j] = 0
else:
dis[i][j] = min(dis[i+1][j]+1, dis[i][j+1]+1, dis[i][j])
res = max(dis[i][j], res)
return res if res != -1 and res != float("inf") else -1
https://leetcode.com/problems/as-far-from-land-as-possible/
BFS (Oceans as sources)
When using BFS on trees, we don't need to record the visited nodes, since tree is directional graph. But using BFS on matrix, we need to record the visited nodes, because matrix is not directinal graph.
Take oceans as sources, use BFS to find the island layer by layer, the distance to the first found island is the closest island.
The problem is asking for the max distance between an ocean to its closest island. So we need to iterate each ocean and find the each distance between the ocean and its closest island. Then we compare all the distances, and find the max one.
BFS (Islands as sources)
If taking oceans as sources, there are many oceans processed more than once.
To optimize it, we can take islands as sources, then the problem is converted to find the furthest ocean to each island, and the distance between the furthest ocean and the island is the answer.
Because BFS searches layer by layer, so we can put all the islands into the queue (multiple sources), and use BFS to search the oceans. Increment the distance by each layer. When reaching the last layer (the last ocean), we find the answer.
BFS (Oceans as sources, single source)
class Solution {
int[][] DIRS = new int[][] {{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
public int maxDistance(int[][] grid) {
int max = -1;
int n = grid.length;
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
if(grid[i][j] == 0){
max = Math.max(max, bfs(grid, i, j));
}
}
}
return max;
}
private int bfs(int[][] grid, int i, int j){
int n = grid.length;
int[][] visited = new int[n][n];
Queue<int[]> queue = new LinkedList<>();
visited[i][j] = 1;
queue.offer(new int[]{i, j, 0}); // row, column, dist
while(!queue.isEmpty()){
int[] cell = queue.poll();
for(int[] dir: DIRS){
int r = cell[0] + dir[0];
int c = cell[1] + dir[1];
if(isValid(n, r, c) && visited[r][c] == 0){
if(grid[r][c] == 1){
return cell[2] + 1;
}
visited[r][c] = 1;
queue.offer(new int[]{r, c, cell[2] + 1});
}
}
}
return -1;
}
private boolean isValid(int n, int i, int j){
return i >= 0 && i < n && j >= 0 && j < n;
}
}
BFS (Islands as sources, multiple sources)
class Solution {
int[][] DIRS = new int[][]{{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
public int maxDistance(int[][] grid) {
boolean hasOcean = false;
int result = -1;
int n = grid.length;
Queue<int[]> queue = new LinkedList<>();
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
if(grid[i][j] == 1){
queue.offer(new int[]{i, j});
}
}
}
while(!queue.isEmpty()){
int[] cell = queue.poll();
result = grid[cell[0]][cell[1]];
for(int[] dir: DIRS){
int r = cell[0] + dir[0];
int c = cell[1] + dir[1];
if(isValid(n, r, c) && grid[r][c] == 0){
hasOcean = true;
grid[r][c] = grid[cell[0]][cell[1]] + 1;
queue.offer(new int[]{r, c});
}
}
}
return hasOcean? result - 1: -1;
}
private boolean isValid(int n, int i, int j){
return i >= 0 && i < n && j >= 0 && j < n;
}
}
Code:
public class Solution { public int MaxDistance(int[][] grid) {
Queue<int> xQueue = new Queue<int>();
Queue<int> yQueue = new Queue<int>();
int row = grid.Length;
int col = grid[0].Length;
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (grid[i][j] == 1)
{
xQueue.Enqueue(i);
yQueue.Enqueue(j);
}
}
}
if (xQueue.Count == 0 || xQueue.Count == row * col)
return -1;
int[] xDirection = new int[]{1, 0, -1, 0};
int[] yDirection = new int[]{0, 1, 0, -1};
int steps = -1;
while (xQueue.Count > 0)
{
int currentLen = xQueue.Count;
for (int i = 0; i < currentLen; i++)
{
int currentX = xQueue.Dequeue();
int currentY = yQueue.Dequeue();
for (int j = 0; j < 4; j++)
{
int newX = currentX + xDirection[j];
int newY = currentY + yDirection[j];
if (newX < 0 || newX >= grid.Length || newY < 0 || newY >= grid[0].Length || grid[newX][newY] != 0)
continue;
grid[newX][newY] = -1;
xQueue.Enqueue(newX);
yQueue.Enqueue(newY);
}
}
steps++;
}
return steps;
}
}
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()
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
你现在手里有一份大小为 N x N 的 网格 grid,上面的每个 单元格 都用 0 和 1 标记好了。其中 0 代表海洋,1 代表陆地,请你找出一个海洋单元格,这个海洋单元格到离它最近的陆地单元格的距离是最大的。
我们这里说的距离是「曼哈顿距离」( Manhattan Distance):(x0, y0) 和 (x1, y1) 这两个单元格之间的距离是 |x0 - x1| + |y0 - y1| 。
如果网格上只有陆地或者海洋,请返回 -1。
BFS
一开始,我们找出所有陆地格子,将它们放入队列,作为第 0 层的结点。 然后进行 BFS 遍历,每个结点的相邻结点可能是上、下、左、右四个方向的结点,注意判断结点位于网格边界的特殊情况。 当遍历结束时,当前的遍历层数就是海洋格子到陆地格子的最远距离。
为了在遍历中不重复访问海洋格子,我们将已经遍历过的海洋格子的值改为 2,和原来海洋格子里的 0 区别开来。
public int maxDistance(int[][] grid) {
int N = grid.length;
Queue<int[]> queue = new ArrayDeque<>();
//将所有的陆地格子加入队列
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});
}
}
}
//如果我们的地图上只有陆地或者海洋,请返回 -1。
if (queue.isEmpty() || queue.size() == N * N) {
return -1;
}
int distance = -1;
while (!queue.isEmpty()) {
distance++;
int n = queue.size();
//取出 n 个结点,以实现层序遍历
for (int i = 0; i < n; i++) {
int[] cell = queue.poll();
int r = cell[0];
int c = cell[1];
//遍历上方单元格
if (r-1 >= 0 && grid[r-1][c] == 0) {
grid[r-1][c] = 2;
queue.add(new int[]{r-1, c});
}
//遍历下方单元格
if (r+1 < N && grid[r+1][c] == 0) {
grid[r+1][c] = 2;
queue.add(new int[]{r+1, c});
}
//遍历左边单元格
if (c-1 >= 0 && grid[r][c-1] == 0) {
grid[r][c-1] = 2;
queue.add(new int[]{r, c-1});
}
//遍历右边单元格
if (c+1 < N && grid[r][c+1] == 0) {
grid[r][c+1] = 2;
queue.add(new int[]{r, c+1});
}
}
}
return distance;
}
参考力扣官方题解给出
时间复杂度:$O(n^4)$
空间复杂度:$O(n^2)$
BFS
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
level = 0
while q:
size = len(q)
for _ in range(size):
i,j = q.popleft()
for x,y in [(1,0), (-1, 0), (0, 1), (0, -1)]:
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
#将所有陆地加入队列
#陆地不断扩展到海洋,每扩展一次就steps加1,直到无法扩展。
#返回steps。
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
n = len(grid)
steps = -1
q = 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
move = [(-1, 0), (1, 0), (0, -1), (0, 1)]
while len(q) > 0:
for _ in range(len(q)):
x, y = q.popleft()
for dx, dy in move:
nx, ny = x + dx, y + dy
if 0 <= nx < n and 0 <= ny < n and grid[nx][ny] == 0:
q.append((nx, ny))
grid[nx][ny] = -1
steps += 1
return steps
第一次写bfs,思路借鉴大佬,以陆地为中心,每层次遍历一次ans+1
type Point struct {
X int
Y int
}
func maxDistance(grid [][]int) int {
var queue []*Point
for i := 0; i < len(grid); i++ {
for j := 0; j < len(grid[0]); j++ {
if grid[i][j] == 1 {
queue = append(queue, &Point{i, j})
}
}
}
if len(queue) == 0 || len(queue) == len(grid)*len(grid[0]) {
return -1
}
ans := 0
d := [4][2]int{{1, 0}, {0, 1}, {-1, 0}, {0, -1}}
for len(queue) > 0{
ans++
tmpQueu := queue
queue = nil
for len(tmpQueu) > 0 {
p := tmpQueu[0]
tmpQueu = tmpQueu[1:]
for i := 0; i < 4; i++ {
x := p.X + d[i][0]
y := p.Y + d[i][1]
if x < 0 || x >= len(grid) || y < 0 || y >= len(grid[0]) || grid[x][y] != 0 {
continue
}
queue = append(queue, &Point{x, y})
grid[x][y] = 2
}
}
}
return ans-1
}
时间:O(n4) 空间:O(n2)
多源BFS搜索
class Solution {
public int maxDistance(int[][] grid) {
int m = grid.length;
int n = grid[0].length;
Queue<int[]> q = new LinkedList<>();
boolean[][] seen = new boolean[m][n];
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});
seen[i][j] = true;
}
}
}
int[] dx = {1, 0, -1, 0};
int[] dy = {0, 1, 0, -1};
int maxDist = -1;
while (!q.isEmpty()) {
int size = q.size();
for (int i=0; i<size; i++) {
int[] cur = q.poll();
for (int k=0; k<4; k++) {
int row = cur[0] + dx[k];
int col = cur[1] + dy[k];
if (row >= 0 && row < m && col >= 0 && col < n && !seen[row][col]) {
q.offer(new int[]{row, col});
seen[row][col] = true;
}
}
}
maxDist++;
}
return maxDist == 0 ? -1 : maxDist;
}
}
TC: O(mn) SC: O(mn)
Thoughts BFS
Code
public int maxDistance(int[][] grid) {
int[] dx = {0, 0, 1, -1};
int[] dy = {1, -1, 0, 0};
Queue<int[]> queue = new ArrayDeque<int[]>();
int m = grid.length, n = grid[0].length;
// put land into queue
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});
}
}
}
boolean hasOcean = false;
int[] point = null;
while (!queue.isEmpty()) {
point = queue.poll();
int x = point[0], y = point[1];
for (int i = 0; i < 4; i++) {
int newX = x + dx[i];
int newY = y + dy[i];
if (newX < 0 || newX >= m || newY < 0 || newY >= n || grid[newX][newY] != 0) {
continue;
}
grid[newX][newY] = grid[x][y] + 1;
hasOcean = true;
queue.offer(new int[]{newX, newY});
}
}
if (point == null || !hasOcean) {
return -1;
}
return grid[point[0]][point[1]] - 1;
}
Complexity Time:O(n^2) Space: O(n)
from collections import deque
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
dq = deque()
n = len(grid)
for i in range(n):
for j in range(n):
if grid[i][j]:
dq.append((i , j , 1))
dx = [0,1,0,-1]
dy = [1,0,-1,0]
ans = -1
if len(dq) == n * n or len(dq) == 0 :
return -1
x , y = 0 , 0
while dq:
x , y ,dis = dq.popleft()
for i in range(4):
cx , cy = x + dx[i] , y + dy[i]
if cx >= 0 and cx < n and cy >= 0 and cy < n and not grid[cx][cy]:
dq.append((cx,cy,dis + 1))
grid[cx][cy] = dis + 1
return grid[x][y]-1
type pos struct{
x,y int
}
func maxDistance(grid [][]int) int {
m := len(grid)
n := len(grid[0])
out := -1
steps := [4][2]int{{1,0},{-1,0},{0,1},{0,-1}}
queue := []pos{}
for i,x:= range grid{
for j := range x{
if x[j] == 1{
queue = append(queue,pos{i,j})
}
}
}
if len(queue) == 0 || len(queue) == m*n{
return -1
}
for len(queue) > 0{
length := len(queue)
for i:=0;i<length;i++{
q := queue[0]
queue = queue[1:]
for j:=0;j<4;j++{
x := q.x+steps[j][0]
y := q.y+steps[j][1]
if x <0 || x >= m ||y<0||y>=n||grid[x][y]!=0{
continue
}
queue = append(queue,pos{x,y})
grid[x][y] = 1
}
}
out++
}
return out
}
BFS through each island
class Solution {
public int maxDistance(int[][] grid) {
boolean[][] visited = new boolean[grid.length][grid[0].length];
LinkedList<int[]> queue = new LinkedList<int[]>();
//add all island to queue
for(int i = 0; i < grid.length; i++){
for(int j = 0; j < grid[0].length; j++){
if(grid[i][j] == 1){
queue.add(new int[]{i,j});
grid[i][j] = 0;
visited[i][j] = true;
}else{
grid[i][j] = Integer.MIN_VALUE;
}
}
}
int maxDep = -1;
while(!queue.isEmpty()){
int[] curr = queue.poll();
int x = curr[0];
int y = curr[1];
visited[x][y] = true;
if(x - 1 >= 0 && grid[x-1][y] < 0){
grid[x-1][y] = grid[x][y] + 1;
maxDep = Math.max(maxDep, grid[x-1][y]);
queue.add(new int[]{x-1,y});
}
if(y - 1 >= 0 && grid[x][y-1] < 0){
grid[x][y-1] = grid[x][y] + 1;
maxDep = Math.max(maxDep, grid[x][y-1]);
queue.add(new int[]{x,y-1});
}
if(x + 1 <= grid.length - 1 && grid[x+1][y] < 0){
grid[x+1][y] = grid[x][y] + 1;
maxDep = Math.max(maxDep, grid[x+1][y]);
queue.add(new int[]{x+1,y});
}
if(y + 1 <= grid[0].length - 1 && grid[x][y+1] < 0){
grid[x][y+1] = grid[x][y] + 1;
maxDep = Math.max(maxDep, grid[x][y+1]);
queue.add(new int[]{x,y+1});
}
}
// System.out.println(queue);
return maxDep == -1? -1:maxDep;
}
}
复杂度分析
思路: 先找到所有的陆地,然后通过BFS的方法(每次将陆地旁的所有海洋转换为陆地,并count++),直到没有陆地为止
type Point struct {
X int
Y int
}
func maxDistance(grid [][]int) int {
var queue []*Point
for i:=0; i < len(grid); i++ {
for j:=0; j < len(grid[0]); j++ {
if grid[i][j] == 1 {
queue = append(queue, &Point{i, j})
}
}
}
if len(queue) == 0 || len(queue) == len(grid)*len(grid[0]) {
return -1
}
ans := 0
d := [4][2]int{{1, 0}, {0, 1}, {-1, 0}, {0, -1}}
for len(queue) > 0 {
ans++
tmpQueu := queue
queue = nil
for len(tmpQueu) > 0 {
p := tmpQueu[0]
tmpQueu = tmpQueu[1:]
// 以p为原点,检查4个方向
for i:=0; i < 4; i++ {
x := p.X + d[i][0]
y := p.Y + d[i][1]
if x < 0 || x >= len(grid) || y < 0 || y >= len(grid[0]) || grid[x][y] != 0 {
continue
}
queue = append(queue, &Point{x, y})
grid[x][y] = 2 // 代表以及被遍历过了
}
}
}
return ans-1
}
时间复杂度:O(N2) 空间复杂度:O(N2)
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
n = len(grid)
total_water = n ** 2
queue = deque()
for i in range(n):
for j in range(n):
if grid[i][j] == 1:
queue.append((i, j))
total_water -= 1
if total_water == n ** 2 or total_water == 0:
return -1
steps = 0
while queue:
curlevel = queue
queue = []
for r,c in curlevel:
if grid[r][c] == 0:
grid[r][c] = 1
total_water -= 1
if total_water == 0:
return steps
for nr, nc in [(r+1, c), (r-1, c), (r, c+1), (r, c-1)]:
if 0 <= nr < n and 0 <= nc < n and grid[nr][nc] == 0:
queue.append((nr, nc))
steps += 1
islands
class Solution {
int[][] dirs = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
public int maxDistance(int[][] grid) {
int n = grid.length;
Deque<int[]> dq = new LinkedList<>();
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
if(grid[i][j] == 1){
dq.addLast(new int[]{i, j});
grid[i][j] = -1;
}
}
}
int ans = -1;
while(!dq.isEmpty()){
int[] poll = dq.pollFirst();
int dx = poll[0], dy = poll[1];
int step = Math.max(grid[dx][dy], 0);
for(int[] dir : dirs){
int nx = dx + dir[0], ny = dy + dir[1];
if(nx < 0 || ny < 0 || nx >= n || ny >= n){
continue;
}
if(grid[nx][ny] != 0){
continue;
}
dq.addLast(new int[]{nx, ny});
grid[nx][ny] = step + 1;
ans = Math.max(ans, step + 1);
}
}
return ans;
}
}
复杂度分析
BFS。
学习了官方题解的方法。
从陆地开始进行遍历。因为陆地距离自己的距离是 0,我们就至少获得了一些已知距离的点。 从这些已知距离的点出发,我们依次访问距离当前点距离为 1 的其他点,更新那些点和陆地之间的距离(即,当前点到陆地的距离加 1)。 因为 BFS 的特性,我们得到的距离就是最短距离。
最后从所水域点中找到距离长的就可以了。
CPP
class Solution {
static constexpr int dx[] = {-1, 1, 0, 0};
static constexpr int dy[] = {0, 0, -1, 1};
public:
int maxDistance(vector<vector<int>>& grid) {
int N = grid.size();
// dist stores the distance from the current point to the nearest land
vector<vector<int>> dist(N, vector(N, INT_MAX));
queue<pair<int, int>> points;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (grid[i][j] == 1) {
dist[i][j] = 0;
points.push(pair(i, j));
}
}
}
// start from the land, so we can update dist from the point next to the current one
while (!points.empty()) {
auto [prev_x, prev_y] = points.front();
points.pop();
// this four points have only 1 distance from the prev point
for (int i = 0; i < 4; i++) {
int x = prev_x + dx[i];
int y = prev_y + dy[i];
if (x < 0 || y < 0 || x >= N || y >= N) {
continue; // out of range
}
if (dist[x][y] > dist[prev_x][prev_y] + 1) {
// this point(x, y) has not be visited yet
dist[x][y] = dist[prev_x][prev_y] + 1;
points.push(pair(x, y));
}
}
}
// We get all distants now, find the greatest
int ans = -1;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (grid[i][j] == 0 && dist[i][j] < INT_MAX)
ans = max(ans, dist[i][j]);
}
}
return ans;
}
};
复杂度分析
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
n = len(grid)
step = -1
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 step
while queue:
for _ in range(len(queue)):
x, y = queue.popleft()
for cur_x, cur_y in [(x - 1, y), (x + 1, y), (x, y + 1), (x, y - 1)]:
if 0 <= cur_x < n and 0 <= cur_y < n and grid[cur_x][cur_y] == 0:
queue.append((cur_x, cur_y))
grid[cur_x][cur_y] = -1
step += 1
return step
Time complexity O(n^2) Space complexity 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
思路
1 <= n <= 100,因此不考虑深度优先。如果是广度优先搜索,考虑将陆地入栈,一圈圈地找海洋。
代码
var maxDistance = function(grid) {
let n = grid.length;
let queue = [];
for(let i = 0; i < n; i++){
for(let j = 0; j < n; j++){
if(grid[i][j] === 1) queue.push([i, j]);
}
};
if(queue.length === 0 || queue.length === n * n) return -1;
let step = -1;
let dir = [[-1, 0], [1, 0], [0, 1], [0, -1]];
while(queue.length){
let len = queue.length;
for(let _ = 0; _ < len; _++){
let position = queue.shift();
for(let i = 0; i < 4; i++){
let x = position[0] + dir[i][0];
let y = position[1] + dir[i][1];
if(x >= 0 && x < n && y >= 0 && y < n && grid[x][y] === 0){
grid[x][y] = -1;
queue.push([x, y]);
}
}
};
step++;
};
return step;
};
复杂度分析
var maxDistance = function(grid) {
var land = [];
var ocean = [];
//记录 陆地和海洋
for (var i = 0;i < grid.length;i++) {
for (var j = 0;j < grid.length;j++) {
if (grid[i][j]) {
land.push([i, j]);
}else {
ocean.push([i, j]);
}
}
}
if (land.length == 0||ocean.length == 0) {
return -1;//没有海洋或没有陆地
}
//求每一个海洋区域跟所有陆地的最小距离,
//然后在所有最小距离中求最大距离,就是所有海洋离陆地最远的距离
var max = -1;
for (var i = 0;i < ocean.length;i++) {
//求一片海洋到所有陆地的距离中最小的距离
var min = Infinity;
for (var j = 0;j < land.length;j++) {
var dis = Math.abs(ocean[i][0] - land[j][0]) + Math.abs(ocean[i][1] - land[j][1])
if (dis < min) {
min = dis;
}
if (min == 1) {
break;//提前结束,最小可能的距离是1
}
}
//求最小距离中的最大距离
if (min > max) {
max = min;
}
}
return max;
};
class Solution {
public:
int maxDistance(vector<vector<int>>& grid) {
queue<pair<int, int>> que;
int size = grid.size();
for (int i = 0; i < size; ++i){
for (int j = 0; j < size; ++j){
if (grid[i][j] == 1) que.push(make_pair(i, j));
}
}
if (que.size() == 0 || que.size() == size * size) return -1;
int res = 0;
while (!que.empty()){
int temp = que.size();
while(temp --){
auto front = que.front();
que.pop();
int row = front.first, col = front.second;
if (row != 0 && grid[row - 1][col] == 0){
que.push(make_pair(row - 1, col));
grid[row - 1][col] = 1;
}
if (row != size - 1 && grid[row + 1][col] == 0){
que.push(make_pair(row + 1, col));
grid[row + 1][col] = 1;
}
if (col != 0 && grid[row][col - 1] == 0){
que.push(make_pair(row, col - 1));
grid[row][col - 1] = 1;
}
if (col != size - 1 && grid[row][col + 1] == 0){
que.push(make_pair(row, col + 1));
grid[row][col + 1] = 1;
}
}
res ++;
}
return --res;
}
};
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
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
++
你现在手里有一份大小为 n x n
的 网格 grid
,上面的每个 单元格 都用 0
和 1
标记好了。其中 0
代表海洋,1
代表陆地,请你找出一个海洋单元格,这个海洋单元格到离它最近的陆地单元格的距离是最大的。如果网格上只有陆地或者海洋,请返回 -1
。
我们这里说的距离是「曼哈顿距离」( Manhattan Distance):(x0, y0)
和 (x1, y1)
这两个单元格之间的距离是 |x0 - x1| + |y0 - y1|
。
class Solution {
public:
int maxDistance(vector<vector<int>>& grid) {
// BFS
queue<vector<int>> lands;
vector<pair<int, int>> dev = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
for(int i = 0; i < grid.size(); i++){
for(int j = 0; j < grid[0].size(); j++){
if(grid[i][j] == 1){
vector<int> tmp = {i, j};
lands.push(tmp);
}
}
}
int res = -1;
bool hasOcean = false;
vector<int> point;
while(!lands.empty()){
//for(int k = 0; k < lands.size(); k++){
point = lands.front();
lands.pop();
int i = point[0];
int j = point[1];
for(auto& d: dev){
int x = i + d.first;
int y = j + d.second;
if(x < 0 || x >= grid.size() || y < 0 || y >= grid[0].size() || grid[x][y] != 0){
continue;
}
hasOcean = true;
grid[x][y] = grid[i][j] + 1;
// res = max(res, grid[x][y]);
vector<int> t = {x, y};
lands.push(t);
}
//}
}
if(!hasOcean){
return -1;
}
return grid[point[0]][point[1]] - 1;
}
};
参考题解
/**
* @param {number[][]} grid
* @return {number}
*/
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
}
};
复杂度分析
class Solution {
static int[] dx = {-1, 0, 1, 0};
static int[] dy = {0, 1, 0, -1};
int n;
int[][] grid;
public int maxDistance(int[][] grid) {
this.n = grid.length;
this.grid = grid;
int ans = -1;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] == 0) {
ans = Math.max(ans, findNearestLand(i, j));
}
}
}
return ans;
}
public int findNearestLand(int x, int y) {
boolean[][] vis = new boolean[n][n];
Queue<int[]> queue = new LinkedList<int[]>();
queue.offer(new int[]{x, y, 0});
vis[x][y] = true;
while (!queue.isEmpty()) {
int[] f = queue.poll();
for (int i = 0; i < 4; ++i) {
int nx = f[0] + dx[i], ny = f[1] + dy[i];
if (!(nx >= 0 && nx < n && ny >= 0 && ny < n)) {
continue;
}
if (!vis[nx][ny]) {
queue.offer(new int[]{nx, ny, f[2] + 1});
vis[nx][ny] = true;
if (grid[nx][ny] == 1) {
return f[2] + 1;
}
}
}
}
return -1;
}
}
思路
如何获取结点与初始结点的距离?
java code
class Solution {
public int maxDistance(int[][] grid) {
int ans = -1;
for(int i = 0;i<grid.length;i++){
for(int j = 0;j<grid[i].length;j++){
if(grid[i][j]==0){
ans = Math.max(ans, bfs(grid,i,j));
}
}
}
return ans;
}
public int bfs(int[][] grid,int i,int j){
boolean[][] visited = new boolean[grid.length][grid.length];
Queue<int[]> queue = new LinkedList<>();
queue.offer(new int[]{i,j,0});
visited[i][j] = true;
while(!queue.isEmpty()){
int[] poll = queue.poll();
int x = poll[0];
int y = poll[1];
if(x>0&&!visited[x-1][y]){
visited[x-1][y] = true;
queue.offer(new int[]{x-1,y,poll[2]+1});
if(grid[x-1][y]==1){
return poll[2]+1;
}
}
if(x<grid.length-1&&!visited[x+1][y]){
visited[x+1][y] = true;
queue.offer(new int[]{x+1,y,poll[2]+1});
if(grid[x+1][y]==1){
return poll[2]+1;
}
}
if(y>0&&!visited[x][y-1]){
visited[x][y-1] = true;
queue.offer(new int[]{x,y-1,poll[2]+1});
if(grid[x][y-1]==1){
return poll[2]+1;
}
}
if(y<grid.length-1&&!visited[x][y+1]){
visited[x][y+1] = true;
queue.offer(new int[]{x,y+1,poll[2]+1});
if(grid[x][y+1]==1){
return poll[2]+1;
}
}
}
return -1;
}
}
时间:O($n^4$)
空间:O($n^2$)
var maxDistance = function (grid) {
let land = [];
let ocean = [];
for (let i = 0; i < grid.length; i++) {
for (let j = 0; j < grid.length; j++) {
if (grid[i][j]) {
land.push([i, j]);
} else {
ocean.push([i, j]);
}
}
}
if (land.length == 0 || ocean.length == 0) {
return -1;
}
let max = -1;
for (let i = 0; i < ocean.length; i++) {
let min = Infinity;
for (let j = 0; j < land.length; j++) {
let d = distance(ocean[i], land[j]);
if (d < min) {
min = d;
}
if (min == 1) {
break;
}
}
if (min > max) {
max = min;
}
}
return max;
};
function distance(a, b) {
return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]);
}
class Solution {
const int dx[4] = {0, 1, 0, -1};
const int dy[4] = {1, 0, -1, 0};
public:
int maxDistance(vector<vector
}
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
class Solution:
def maxDistance(self, grid):
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
class Solution {
const int dx[4] = {0, 1, 0, -1};
const int dy[4] = {1, 0, -1, 0};
public:
int maxDistance(vector<vector
}
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;
}
};
grid
值表示访问过,BFS时找到1就停下来,并将所有修改过的grid值还原,复杂度$O(n^4)$,实际情况会有剪枝,以6800ms+在LC上通过。class Solution:
# BFS+遍历:遍历所有格子,如果是0就开始BFS,更改`grid`值表示访问过,BFS时找到1就停下来,并将所有修改过的grid值还原,
# 复杂度$O(n^4)$,实际情况会有剪枝,以6800ms+在LC上通过。
def maxDistance1(self, grid: List[List[int]]) -> int:
n = len(grid)
directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]
def bfs(i, j):
q = deque([(i, j)])
grid[i][j] = -1
tmp = [(i, j)]
cnt = 0
while q:
cnt += 1
for _ in range(len(q)):
i, j = q.popleft()
for dx, dy in directions:
x, y = i + dx, j + dy
if 0 <= x < n and 0 <= y < n:
if grid[x][y] == 0:
grid[x][y] = -1
tmp.append((x, y))
q.append((x, y))
elif grid[x][y] == 1:
for i, j in tmp:
grid[i][j] = 0
return cnt
return -1
ans = -1
for i, j in product(range(n), range(n)):
if grid[i][j] == 0:
ans = max(bfs(i, j), ans)
return ans
# BFS:找到所有的1,同时向四周开始BFS,直到覆盖了全图。(感觉上就像所有的点向四周发射一圈波,所有波产生干涉的时候就是
# 结果)。复杂度$O(n^2)$。
def maxDistance(self, grid: List[List[int]]) -> int:
n = len(grid)
directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]
q = deque()
for i, j in product(range(n), range(n)):
if grid[i][j] == 1:
q.append((i, j))
if len(q) == n * n or not q:
return -1
cnt = -1
while q:
cnt += 1
for _ in range(len(q)):
i, j = q.popleft()
for dx, dy in directions:
x, y = i + dx, j + dy
if 0 <= x < n and 0 <= y < n and grid[x][y] == 0:
q.append((x, y))
grid[x][y] = -1
return cnt
BFS
class Solution {
public int maxDistance(int[][] grid) {
int[] dx = {0, 0, 1, -1};
int[] dy = {1, -1, 0, 0};
Queue<int[]> queue = new ArrayDeque<>();
int m = grid.length, n = grid[0].length;
// 先把所有的陆地都入队。
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});
}
}
}
// 从各个陆地开始,一圈一圈的遍历海洋,最后遍历到的海洋就是离陆地最远的海洋。
boolean hasOcean = false;
int[] point = null;
while (!queue.isEmpty()) {
point = queue.poll();
int x = point[0], y = point[1];
// 取出队列的元素,将其四周的海洋入队。
for (int i = 0; i < 4; i++) {
int newX = x + dx[i];
int newY = y + dy[i];
if (newX < 0 || newX >= m || newY < 0 || newY >= n || grid[newX][newY] != 0) {
continue;
}
grid[newX][newY] = grid[x][y] + 1; // 这里我直接修改了原数组,因此就不需要额外的数组来标志是否访问
hasOcean = true;
queue.offer(new int[] {newX, newY});
}
}
// 没有陆地或者没有海洋,返回-1。
if (point == null || !hasOcean) {
return -1;
}
// 返回最后一次遍历到的海洋的距离。
return grid[point[0]][point[1]] - 1;
}
}
TIme O(N^2) Space O(N^2)
class Solution {
int n;
int[][] grid;
public int maxDistance(int[][] _grid) {
grid = _grid;
n = grid.length;
int ans = -1;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 0) {
ans = Math.max(ans, bfs(i, j));
}
}
}
return ans;
}
// 单次 BFS:求解海洋位置 (x,y) 最近的陆地距离
int bfs(int x, int y) {
int[][] dirs = new int[][]{{1,0},{-1,0},{0,1},{0,-1}};
Deque<int[]> d = new ArrayDeque<>();
Map<Integer, Integer> map = new HashMap<>();
d.addLast(new int[]{x, y});
map.put(x * n + y, 0);
while (!d.isEmpty()) {
int[] poll = d.pollFirst();
int dx = poll[0], dy = poll[1];
int step = map.get(dx * n + dy);
if (grid[dx][dy] == 1) return step;
for (int[] di : dirs) {
int nx = dx + di[0], ny = dy + di[1];
if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
int key = nx * n + ny;
if (map.containsKey(key)) continue;
d.addLast(new int[]{nx, ny});
map.put(key, step + 1);
}
}
return -1;
}
}
class Solution {
public int maxDistance(int[][] grid) {
int[] dx = {0, 0, 1, -1};
int[] dy = {1, -1, 0, 0};
Queue<int[]> queue = new ArrayDeque<>();
int m = grid.length, n = grid[0].length;
// 先把所有的陆地都入队。
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});
}
}
}
// 从各个陆地开始,一圈一圈的遍历海洋,最后遍历到的海洋就是离陆地最远的海洋。
boolean hasOcean = false;
int[] point = null;
while (!queue.isEmpty()) {
point = queue.poll();
int x = point[0], y = point[1];
// 取出队列的元素,将其四周的海洋入队。
for (int i = 0; i < 4; i++) {
int newX = x + dx[i];
int newY = y + dy[i];
if (newX < 0 || newX >= m || newY < 0 || newY >= n || grid[newX][newY] != 0) {
continue;
}
grid[newX][newY] = grid[x][y] + 1; // 这里我直接修改了原数组,因此就不需要额外的数组来标志是否访问
hasOcean = true;
queue.offer(new int[] {newX, newY});
}
}
// 没有陆地或者没有海洋,返回-1。
if (point == null || !hasOcean) {
return -1;
}
// 返回最后一次遍历到的海洋的距离。
return grid[point[0]][point[1]] - 1;
}
}
BFS。官方题解
import java.util.LinkedList;
import java.util.Queue;
public class Solution {
int[] dx = {-1, 0, 1, 0};
int[] dy = {0, 1, 0, -1};
int n;
int[][] grid;
public int maxDistance(int[][] grid) {
this.n = grid.length;
this.grid = grid;
int ans = -1;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] == 0) {
ans = Math.max(ans, findNearestLand(i, j));
}
}
}
return ans;
}
public int findNearestLand(int x, int y) {
boolean[][] vis = new boolean[n][n];
Queue<int[]> queue = new LinkedList<int[]>();
queue.offer(new int[]{x, y, 0});
vis[x][y] = true;
while (!queue.isEmpty()) {
int[] f = queue.poll();
for (int i = 0; i < 4; ++i) {
int nx = f[0] + dx[i], ny = f[1] + dy[i];
if (!(nx >= 0 && nx < n && ny >= 0 && ny < n)) {
continue;
}
if (!vis[nx][ny]) {
queue.offer(new int[]{nx, ny, f[2] + 1});
vis[nx][ny] = true;
if (grid[nx][ny] == 1) {
return f[2] + 1;
}
}
}
}
return -1;
}
}
复杂度分析
import java.util.LinkedList;
import java.util.Queue;
public class Solution {
int[] dx = {-1, 0, 1, 0};
int[] dy = {0, 1, 0, -1};
int n;
int[][] grid;
public int maxDistance(int[][] grid) {
this.n = grid.length;
this.grid = grid;
int ans = -1;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (grid[i][j] == 0) {
ans = Math.max(ans, findNearestLand(i, j));
}
}
}
return ans;
}
public int findNearestLand(int x, int y) {
boolean[][] vis = new boolean[n][n];
Queue<int[]> queue = new LinkedList<int[]>();
queue.offer(new int[]{x, y, 0});
vis[x][y] = true;
while (!queue.isEmpty()) {
int[] f = queue.poll();
for (int i = 0; i < 4; ++i) {
int nx = f[0] + dx[i], ny = f[1] + dy[i];
if (!(nx >= 0 && nx < n && ny >= 0 && ny < n)) {
continue;
}
if (!vis[nx][ny]) {
queue.offer(new int[]{nx, ny, f[2] + 1});
vis[nx][ny] = true;
if (grid[nx][ny] == 1) {
return f[2] + 1;
}
}
}
}
return -1;
}
}
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;
}
};
/*
# Logic:
BFS from each water cell, keep track of the max distance - duplicate work
BFS from each land cell instead
# Complexity:
Time:O(m*n), worst case, m = grid.length, n = grid[0].length
O(n^2)
Space: for the queue, worst O(m*n), O(n^2) specified in constraints
// [[1,0],[0,1]] ->1
// [[1,0],[0,0]] -> 2
Queue:(0,0)
size = 1
queue:(0,1),(1,0)
max=0
size = 2
queue:(1,1)
max = 1
size = 1
queue, empty
max = 2
*/
class Solution {
public int maxDistance(int[][] grid) {
int n = grid.length;
if (grid == null || n == 0) return -1;
int maxDist = -1;
Queue<int[]> nodeQueue = new LinkedList<>();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 1) {
nodeQueue.offer(new int[]{i, j});
}
}
}
// no water/no land
if (nodeQueue.size() == 0 || nodeQueue.size() == n * n)
return -1;
// bfs
while (!nodeQueue.isEmpty()) {
int size = nodeQueue.size();
for (int k = 0; k < size; k++) {
int[] cur = nodeQueue.poll();
int curRow = cur[0];
int curCol = cur[1];
if (curRow - 1 >= 0 && grid[curRow-1][curCol] == 0) {
nodeQueue.add(new int[]{curRow-1,curCol});
// mark visited
grid[curRow-1][curCol] = -1;
}
if (curRow + 1 < grid.length && grid[curRow+1][curCol] == 0) {
nodeQueue.add(new int[]{curRow+1,curCol});
// mark visited
grid[curRow+1][curCol] = -1;
}
if (curCol - 1 >= 0 && grid[curRow][curCol - 1] == 0) {
nodeQueue.add(new int[]{curRow,curCol - 1});
// mark visited
grid[curRow][curCol - 1] = -1;
}
if (curCol + 1 < grid[0].length && grid[curRow][curCol + 1] == 0) {
nodeQueue.add(new int[]{curRow,curCol + 1});
// mark visited
grid[curRow][curCol + 1] = -1;
}
}
maxDist++;
}
return maxDist;
}
}
思路:
广度优先遍历(BFS)
复杂度分析:
代码(C++):
方法二(BFS)、
class Solution {
public:
int maxDistance(vector<vector<int>>& grid) {
if (grid.empty()) return -1;
int res = -1;
int w = 0, l = 0;
int n = grid.size();
queue<pair<int, int>> qt;
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
if (grid[i][j])
qt.push({i, j});
if (qt.empty() || qt.size() == n * n) return -1;
vector<int> dirs = {0, 1, 0, -1, 0};
while (!qt.empty()) {
size_t sz = qt.size();
while (sz--) {
pair<int, int> node = qt.front();
qt.pop();
int y = node.first;
int x = node.second;
for (int i = 0; i < 4; ++i) {
int dy = y + dirs[i];
int dx = x + dirs[i + 1];
if (dy < 0 || dy >= n|| dx < 0 || dx >= n) continue;
if (grid[dy][dx] == 0) {
qt.push({dy, dx});
grid[dy][dx] = 2;
}
}
}
++res;
}
return res;
}
};
1162. 地图分析
入选理由
暂无
题目地址
https://leetcode-cn.com/problems/as-far-from-land-as-possible/
前置知识
暂无
题目描述