方法一:DFS(深度优先搜索)
深度优先搜索一般用于树或者图的遍历,其他有分支的(如二维矩阵)也适用。它的原理是从初始点开始,一直沿着同一个分支遍历,直到该分支结束,然后回溯到上一级继续沿着一个分支走到底,如此往复,直到所有的节点都有被访问到。
使用深度优先搜索(dfs):遍历矩阵,当遇到矩阵的某个元素为1时,首先将其置为了0,然后查看与它相邻的上下左右四个方向,如果这四个方向任意相邻元素为1,则进入该元素,进入该元素之后我们发现又回到了刚刚的子问题,又是把这一片相邻区域的1全部置为0,可以用递归实现。这样就将一个岛全部置0了。继续向下遍历矩阵重新进入上述的case。
时间复杂度:o(nm)。n、m为矩阵的行数和列数
空间复杂度:o(nm)。n、m为矩阵的行数和列数
class Solution {
public:
int solve(vector<vector<char> >& grid) {
int n = grid.size(); //行数
int m = grid[0].size(); //列数
//特殊情况处理(空矩阵)
if(n == 0)
return 0;
int count = 0;
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
if(grid[i][j] == '1') {
count++;
//广度优先搜索
dfs(grid, i, j, n, m);
}
}
}
return count;
}
private:
void dfs(vector<vector<char> >& grid, int row, int col, int maxRow, int maxCol) {
grid[row][col] = '0';
//上方
if(grid[row - 1][col] == '1' && row > 0)
dfs(grid, row - 1, col, maxRow, maxCol);
//下方
if(grid[row + 1][col] == '1' && row + 1 < maxRow)
dfs(grid, row + 1, col, maxRow, maxCol);
//左侧
if(grid[row][col - 1] == '1' && col > 0)
dfs(grid, row, col - 1, maxRow, maxCol);
//右侧
if(grid[row][col + 1] == '1' && col + 1 < maxCol)
dfs(grid, row, col + 1, maxRow, maxCol);
return;
}
};
方法二:BFS(广度优先搜索)
广度优先搜索与深度优先搜索不同,它是将与某个节点直接相连的其它所有节点依次访问一次之后,再往更深处,进入与其他节点直接相连的节点。bfs的时候我们常常会借助队列的先进先出,因为从某个节点出发,我们将与它直接相连的节点都加入队列,它们优先进入,则会优先弹出,在它们弹出的时候再将与它们直接相连的节点加入,由此就可以依次按层访问。
思路:
统计岛屿的方法可以和方法一同样遍历解决,为了去重我们还是要将所有相邻的1一起改成0,这时候同样遍历连通的广度优先搜索(bfs)可以代替dfs。
具体做法:
- step 1:优先判断空矩阵等情况。
- step 2:从上到下从左到右遍历矩阵每一个位置的元素,如果该元素值为1,统计岛屿数量。
- step 3:使用bfs将遍历矩阵遇到的1以及相邻的1全部置为0:利用两个队列辅助(C++可以使用pair),每次队列进入第一个进入的1,然后遍历队列,依次探讨队首的四个方向,是否符合,如果符合则置为0,且位置坐标加入队列,继续遍历,直到队列为空。
时间复杂度:o(nm)。n、m为矩阵的行数和列数
空间复杂度:o(nm)。n、m为矩阵的行数和列数
class Solution {
public:
int solve(vector<vector<char> >& grid) {
int n = grid.size(); //行数
int m = grid[0].size(); //列数
//特殊情况处理(空矩阵)
if (n == 0)
return 0;
int count = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (grid[i][j] == '1') {
count++;
pos_x.push(i);
pos_y.push(j);
grid[i][j] = '0';
// 广度优先搜索
while (!pos_x.empty() && !pos_y.empty()) {
int length = pos_x.size();
for (int i = 0; i < length; i++) {
int row = pos_x.front();
pos_x.pop();
int col = pos_y.front();
pos_y.pop();
//上方
if (grid[row - 1][col] == '1' && row > 0) {
pos_x.push(row - 1);
pos_y.push(col);
grid[row - 1][col] = '0';
}
//下方
if (grid[row + 1][col] == '1' && row + 1 < n) {
pos_x.push(row + 1);
pos_y.push(col);
grid[row + 1][col] = '0';
}
//左侧
if (grid[row][col - 1] == '1' && col > 0) {
pos_x.push(row);
pos_y.push(col - 1);
grid[row][col - 1] = '0';
}
//右侧
if (grid[row][col + 1] == '1' && col + 1 < m) {
pos_x.push(row);
pos_y.push(col + 1);
grid[row][col + 1] = '0';
}
}
}
}
}
}
return count;
}
private:
queue<int> pos_x;
queue<int> pos_y;
};

京公网安备 11010502036488号