LeetCode 934.最短的桥
在给定的二维二进制数组 A 中,存在两座岛。(岛是由四面相连的 1 形成的一个最大组。)
现在,我们可以将 0 变为 1,以使两座岛连接起来,变成一座岛。
返回必须翻转的 0 的最小数目。(可以保证答案至少是 1 。)
// 广度优先搜索 - 通过先入先出的队列实现
class Solution {
public:
vector<int> direction{-1,0,1,0,-1};
int shortestBridge(vector<vector<int>>& grid) {
int m = grid.size(),n = grid[0].size();
queue<pair<int,int>> points; // 队列queue
bool finded = false; // 查找第一座岛
for(int i=0;i<m;++i)
{
for(int j=0;j<n;++j)
{
if(finded) break;
if(grid[i][j] == 1)
{
finded = true;
dfs(grid, points, i, j, m, n); // 深度遍历把第一个岛屿的1全部变成2,并把其旁边的0装入points队列;
}
}
}
// 广度遍历寻找最短距离;
int res = 0;
int x,y;
while(!points.empty())
{
++res; // 第n层广度遍历,n = 最短距离;
int tmp = points.size();
while(tmp--)
{
auto[r,c] = points.front(); // 依次取出第n层广度遍历时的每一个元素;
points.pop();
for(int k=0;k<4;k++) // 判断此元素旁边有无1(岛屿);
{
x = r + direction[k], y = c + direction[k+1];
if(x>=0 && y>=0 && x<m && y<n)
{
if(grid[x][y] == 1) // =1:找到岛屿;
return res;
if(grid[x][y] == 2) // =2:旁边是第一个岛屿,继续循环找;
continue;
points.push({x,y}); // =0;将需要下一层广度遍历的点push到points;
grid[x][y] = 2;
}
}
}
}
return 0;
}
void dfs(vector<vector<int>>& grid, queue<pair<int,int>>& points, int i, int j, int m, int n) {
if(i<0 || j<0 || i==m || j==n || grid[i][j]==2)
return;
if( grid[i][j] == 0)
{
points.push({i,j});
return;
}
grid[i][j] = 2;
dfs(grid, points, i+1, j, m, n);
dfs(grid, points, i-1, j, m, n);
dfs(grid, points, i, j+1, m, n);
dfs(grid, points, i, j-1, m, n);
}
};