LeetCode每日一题——最短的桥

70 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第28天,点击查看活动详情


最近一直在力扣刷题,也逐渐对各类题型有了自己的理解,所谓见招拆招,将自己的浅显经验分享一下,帮助更多在编程路上的朋友们。


最短的桥

给你一个大小为 n x n 的二元矩阵 grid ,其中 1 表示陆地,0 表示水域。

 是由四面相连的 1 形成的一个最大组,即不会与非组内的任何其他 1 相连。grid 中 恰好存在两座岛 。

你可以将任意数量的 0 变为 1 ,以使两座岛连接起来,变成 一座岛 。

返回必须翻转的 0 的最小数目。

 

示例 1:

输入: grid = [[0,1],[1,0]]
输出: 1

示例 2:

输入: grid = [[0,1,0],[0,0,0],[0,0,1]]
输出: 2

示例 3:

输入: grid = [[1,1,1,1,1],[1,0,0,0,1],[1,0,1,0,1],[1,0,0,0,1],[1,1,1,1,1]]
输出: 1

 

提示:

  • n == grid.length == grid[i].length
  • 2 <= n <= 100
  • grid[i][j] 为 0 或 1
  • grid 中恰有两个岛

思路

寻找最近的距离,应该使用BFS,因为DFS会去寻找所有的路径,并不能确定哪条路径的最短的,会更加耗时,BFS可以一层层地扩大距离。

首先需要先找到一个小岛,然后对其标记,再去寻找另一个未进行标记的小岛。

先将一个小岛中的所有位置加入队列中,然后使用BFS去寻找不属于该小岛的陆地,并计算距离,遇到另一个小岛即可停止寻找。

题解

class Solution {
    private int[][] grid;
    private boolean[][] visited;
    private Queue<int[]> queue;
    private int n;
    private int[][] dirs = new int[][]{{-1, 0}, {1, 0}, {0, 1}, {0, -1}};

    public int shortestBridge(int[][] grid) {
        n = grid.length;
        this.grid = grid;
        visited = new boolean[n][n];
        queue = new ArrayDeque<>();
        boolean flag = true;
        for(int i = 0; i < n && flag; i++) {
            for(int j = 0; j < n; j++) {
                if(grid[i][j] == 1) {
                    dfs(i, j);
                    flag = false;
                    break;
                }
            }
        }
        int dist = -1;
        flag = true;
        while(!queue.isEmpty() && flag) {
            int size = queue.size();
            dist++;
            for(int i = 0; i < size && flag; i++) {
                int[] tmp = queue.poll();
                for(int[] dir: dirs) {
                    int x = tmp[0] + dir[0];
                    int y = tmp[1] + dir[1];
                    if(x < 0 || x == n || y < 0 || y == n || visited[x][y]) {
                        continue;
                    }
                    if(grid[x][y] == 1) {
                        flag = false;
                        break;
                    }
                    queue.offer(new int[]{x, y});
                    visited[x][y] = true;
                }
            }
        }
        return dist;
    }

    private void dfs(int x, int y) {
        visited[x][y] = true;
        queue.offer(new int[]{x, y});
        for(int[] dir: dirs) {
            int nx = x + dir[0];
            int ny = y + dir[1];
            if(nx >= 0 && nx < n && ny >= 0 && ny < n && !visited[nx][ny] && grid[nx][ny] == 1) {
                dfs(nx, ny);
            }
        }
    }
}