一.题目

二.思路讲解
2.1 思路讲解
本题与 DFS 解法思路一致,只是将深度优先搜索 改为广度优先搜索。
-
遍历整个网格,每遇到一个未访问的陆地 (
'1'),就找到一个新岛屿,计数加 1。 -
然后使用队列 进行 BFS,从该格子出发,向四个方向扩散,将所有相连的陆地标记为已访问(并入队),直到该岛屿的所有格子都被处理。
三.代码演示
cpp
class Solution
{
public:
int bx[4] = {0,0,1,-1};
int by[4] = {1,-1,0,0};
bool check[301][301];
typedef pair<int,int>PII;
int row;
int col;
int numIslands(vector<vector<char>>& grid)
{
row = grid.size();
col = grid[0].size();
int ret = 0;//统计数量
for(int i = 0;i < row;i++)
{
for(int j = 0;j < col;j++)
{
if(grid[i][j] == '1' && check[i][j] != true)
{
ret++;
bfs(grid,i,j);
}
}
}
return ret;
}
void bfs(vector<vector<char>>& grid,int i,int j)
{
queue<PII>q;
q.push({i,j});
while(q.size())
{
auto [a,b] = q.front();
q.pop();
check[a][b] = true;//标记已使用
for(int k = 0;k < 4;k++)
{
int x = a + bx[k],y = b + by[k];
if(x >= 0 && y >= 0 && x < row && y < col && !check[x][y] && grid[x][y] == '1')
{
check[x][y] = true;
q.push({x,y});
}
}
}
}
};
四.代码讲解
一、全局变量与数据结构
-
bx[4]、by[4]:方向数组,表示上下左右四个方向的偏移量。 -
check[301][301]:布尔数组,标记格子是否已被访问(已属于某个岛屿)。初始值需在函数内清零,此处未显式初始化,但在实际调用中应在numIslands开头使用memset或vector初始化,避免残留数据影响结果。 -
typedef pair<int,int> PII:简化坐标类型的书写。 -
row、col:成员变量,存储网格的行数和列数,便于 BFS 中边界判断。
二、主函数 numIslands
-
获取网格的行数
row和列数col。 -
初始化结果变量
ret = 0。 -
双重循环遍历整个网格:
- 如果当前格子是陆地
'1'且未被访问过(!check[i][j]),则发现一个新岛屿,ret++,并调用 BFS 函数bfs(grid, i, j)将该岛屿的所有陆地标记为已访问。
- 如果当前格子是陆地
-
遍历结束后返回岛屿总数
ret。
三、BFS 函数 bfs
bfs(grid, i, j) 以 (i, j) 为起点,将与其相连的所有陆地标记为已访问。执行流程如下:
-
初始化队列 :创建一个队列
q,将起点(i, j)入队,并立即标记check[i][j] = true(避免重复处理)。 -
循环处理:当队列不为空时,重复以下步骤:
-
取出队头坐标
(a, b)(使用auto [a, b] = q.front(); q.pop();结构绑定)。 -
遍历四个方向,计算新坐标
(x, y)。 -
若新坐标在网格范围内、未被访问(
!check[x][y])、且是陆地'1',则将其标记为已访问(check[x][y] = true),并加入队列。
-
-
队列为空时,该岛屿的所有连通陆地均已处理完毕,函数返回。
四、关键细节
-
入队即标记:在将邻居加入队列前立即标记为已访问,避免同一格子被多次入队,保证每个格子只被处理一次,提高效率。
-
边界检查:每次移动前必须检查坐标合法性,防止越界。
五、流程图
