leetcode-pp / 91alg-6-daily-check

91 算法第六期打卡仓库
28 stars 0 forks source link

【Day 51 】2022-01-31 - 1162. 地图分析 #61

Open azl397985856 opened 2 years ago

azl397985856 commented 2 years ago

1162. 地图分析

入选理由

暂无

题目地址

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:

image


输入:[[1,0,1],[0,0,0],[1,0,1]]
输出:2
解释:
海洋单元格 (1, 1) 和所有陆地单元格之间的距离都达到最大,最大距离为 2。
示例 2:

image


输入:[[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
charlestang commented 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
yetfan commented 2 years ago

思路 陆地找海洋,从所有陆地开始延伸找临近的海洋,一圈圈找直到所有格子被探索过,圈数就是最远距离

代码

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)

laofuWF commented 2 years ago
# 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
wangzehan123 commented 2 years ago

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;
    }
}
youzhaing commented 2 years ago
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
ZacheryCao commented 2 years ago

Idea

BFS

Code:

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

Complexity:

Time: O(mn) Space: O(mn)

LinnSky commented 2 years ago

思路

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
  };
cszys888 commented 2 years ago
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)

feifan-bai commented 2 years ago

思路

  1. bfs岛的问题
  2. deque

代码

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

复杂度分析

ZhangNN2018 commented 2 years ago
        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
ginnydyy commented 2 years ago

Prolbem

https://leetcode.com/problems/as-far-from-land-as-possible/

Notes

Solution

Complexity

moirobinzhang commented 2 years ago

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;     
}

}

Tesla-1i commented 2 years ago
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
xinhaoyi commented 2 years ago

1162. 地图分析

你现在手里有一份大小为 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)$

haixiaolu commented 2 years ago

思路

BFS

代码 / Python

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

复杂度分析:

Alexno1no2 commented 2 years ago
#将所有陆地加入队列
#陆地不断扩展到海洋,每扩展一次就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
Toms-BigData commented 2 years ago

【Day 51】1162. 地图分析

思路

第一次写bfs,思路借鉴大佬,以陆地为中心,每层次遍历一次ans+1

golang代码

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)

tongxw commented 2 years ago

思路

多源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)

rzhao010 commented 2 years ago

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)

ZJP1483469269 commented 2 years ago
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
yan0327 commented 2 years ago
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
}
zwang2244 commented 2 years ago

思路

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;
    }
}

复杂度分析

hdyhdy commented 2 years ago

思路: 先找到所有的陆地,然后通过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)

zol013 commented 2 years ago
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
LannyX commented 2 years ago

思路

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;
    }
}

复杂度分析

z1ggy-o commented 2 years ago

思路

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;
    }
};

复杂度分析

jiaqiliu37 commented 2 years ago
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)

arteecold commented 2 years ago

思路 _ 有一种奇妙探险队的既视感 会不会奇妙探险队真的可以写一个这种金手指

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

复杂性 O(n^2)

1149004121 commented 2 years ago
  1. 地图分析

思路

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;
};

复杂度分析

shamworld commented 2 years ago
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;
};
baddate commented 2 years ago
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;
    }
};
zhiyuanpeng commented 2 years ago
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
wbcz commented 2 years ago

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
dahaiyidi commented 2 years ago

Problem

1162. 地图分析

++

你现在手里有一份大小为 n x n 的 网格 grid,上面的每个 单元格 都用 01 标记好了。其中 0 代表海洋,1 代表陆地,请你找出一个海洋单元格,这个海洋单元格到离它最近的陆地单元格的距离是最大的。如果网格上只有陆地或者海洋,请返回 -1

我们这里说的距离是「曼哈顿距离」( Manhattan Distance):(x0, y0)(x1, y1) 这两个单元格之间的距离是 |x0 - x1| + |y0 - y1|


Note


Complexity


Python

C++

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;
    }
};

From : https://github.com/dahaiyidi/awsome-leetcode

aladingzl commented 2 years ago

思路

参考题解

代码

/**
 * @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
    }
};

复杂度分析

alongchong commented 2 years ago
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;
    }
}
declan92 commented 2 years ago

思路

  1. 使用BFS找到每个海洋单元离陆地最近距离;
  2. 打擂台获取距离最大值;
    细节
  3. 如何获取结点与初始结点的距离?
    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$)

codingPitaya commented 2 years ago
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]);
}
Myleswork commented 2 years ago

class Solution { const int dx[4] = {0, 1, 0, -1}; const int dy[4] = {1, 0, -1, 0};
public: int maxDistance(vector<vector>& grid) { int N = grid.size(); queue<pair<int, int>> q; // queue存储坐标值, 即 pair of {x, y} vector<vector> 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;
}

};

junbuer commented 2 years ago

思路

Hacker90 commented 2 years ago

class Solution { const int dx[4] = {0, 1, 0, -1}; const int dy[4] = {1, 0, -1, 0};
public: int maxDistance(vector<vector>& grid) { int N = grid.size(); queue<pair<int, int>> q; // queue存储坐标值, 即 pair of {x, y} vector<vector> 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;
}

};

CoreJa commented 2 years ago

思路

代码

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
stackvoid commented 2 years ago

思路

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)

zzzpppy commented 2 years ago
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;
    } 
}
machuangmr commented 2 years ago

代码

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;

    }
}
Riuusee commented 2 years ago

思路

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;
    }
}

复杂度分析

Yachen-Guo commented 2 years ago
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;
    }
}
for123s commented 2 years ago
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;
    }
};
taojin1992 commented 2 years ago
/*
# 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;
    }
}
falconruo commented 2 years ago

思路:

广度优先遍历(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;
    }
};