持续创作,加速成长!这是我参与「掘金日新计划 · 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].length2 <= n <= 100grid[i][j]为0或1grid中恰有两个岛
思路
寻找最近的距离,应该使用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);
}
}
}
}