持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第27天,点击查看活动详情
934. 最短的桥
给你一个大小为 n x n 的二元矩阵 grid ,其中 1 表示陆地,0 表示水域。
岛 是由四面相连的 1 形成的一个最大组,即不会与非组内的任何其他 1 相连。grid 中 恰好存在两座岛 。
你可以将任意数量的 0 变为 1 ,以使两座岛连接起来,变成 一座岛 。
返回必须翻转的 0 的最小数目。
限制
n == grid.length == grid[i].length2 <= n <= 100grid[i][j]为0或1grid中恰有两个岛
思路
题目给定我们一个二维化网格的图形,其中包含两个连通块,现在要求你计算两个连通块的最小距离
这道题是一道经典的多源bfs问题。
首先,让我们把这两个连通块的其中一个缩为一个点,然后你就可以发现,我们求的其实是给定起点到任意一个可达终点的最短距离。
那么,现在我们的起点可以是第一个图形的任意一个位置,于是把第一个图形的任意一个位置为起点开始对整个地图做一个bfs即可。
这就是多源bfs。
代码
use std::collections::{BTreeMap, BinaryHeap, HashMap, HashSet, VecDeque};
impl Solution {
pub fn shortest_bridge(grid: Vec<Vec<i32>>) -> i32 {
let ans = 0;
let mut grid = grid;
let (n, m) = (grid.len(), grid[0].len());
let mut que = VecDeque::new();
let xx = [0, 0, -1, 1];
let yy = [1, -1, 0, 0];
fn dfs(
x: usize,
y: usize,
grid: &mut Vec<Vec<i32>>,
que: &mut VecDeque<(usize, usize, i32)>,
) {
let xx = [0, 0, -1, 1];
let yy = [1, -1, 0, 0];
grid[x][y] = 2;
que.push_back((x, y, 0));
let (n, m) = (grid.len(), grid[0].len());
for i in 0..xx.len() {
let dx = x as i32 + xx[i];
let dy = y as i32 + yy[i];
if dx < 0 || dy < 0 {
continue;
}
let dx = dx as usize;
let dy = dy as usize;
if dx >= n || dy >= m || grid[dx][dy] != 1 {
continue;
}
dfs(dx, dy, grid, que);
}
}
let mut flag = 1;
for i in 0..n {
for j in 0..m {
if grid[i][j] == 1 {
dfs(i, j, &mut grid, &mut que);
flag = 0;
}
if flag == 0 {
break;
}
}
if flag == 0 {
break;
}
}
while let Some(t) = que.pop_front() {
for i in 0..xx.len() {
let dx = t.0 as i32 + xx[i];
let dy = t.1 as i32 + yy[i];
if dx < 0 || dy < 0 {
continue;
}
let dx = dx as usize;
let dy = dy as usize;
if dx >= n || dy >= m || grid[dx][dy] == 2 {
continue;
}
if (grid[dx][dy] == 1) {
return t.2;
}
grid[dx][dy] = 2;
que.push_back((dx, dy, t.2 + 1));
}
}
ans
}
}