网格类DFS
我把此类问题归纳为网格类的DFS,典型例题为岛屿标记,下面是该体型类模版,类似题都是根据该模版变形。
模板
1. 遍历过的岛屿需要标记
class Solution {
public:
int numIslands(vector<vector<char>> &grid)
{
int count = 0;
if (grid.size() == 0) return 0;
//遍历网格
for(int i = 0; i < grid.size(); i++) {
for(int j = 0; j < grid[i].size(); j++) {
//如果该格子是1,则该1进行dfs得到连接的所有1组成一个岛屿
if(grid[i][j] == '1') {
dfs(grid, i, j);
count++;//组成岛屿后岛屿数量加一
}
}
}
return count;
}
void dfs(vector<vector<char>> &grid, int row, int col) {
//判断是否到边界,超过边界则return
if(row < 0 || row > grid.size()-1 || col < 0 || col > grid[0].size()-1) return;
//如果当前为1则我们把它标记为2, 如果不是1则我们就return,该点不继续递归
//这里走过的要做标记是为了防止回头遍历,走过的就不走了
if(grid[row][col] == '1') grid[row][col] = '2';
else return;
//上下左右递归
dfs(grid, row-1, col);
dfs(grid, row+1, col);
dfs(grid, row, col-1);
dfs(grid, row, col+1);
}
};
-
- 岛屿数量
-
- 岛屿的周长
-
- 岛屿的最大面积
-
- 不同岛屿的数量
-
- 图像渲染
-
- 被围绕的区域
- 剑指 Offer 13. 机器人的运动范围
2. 遍历过的岛屿需要再次使用的情况
上述几个题遍历过的岛屿标记后就不会再次遍历,而下面几题会在标记后再次使用,这就需要在后序遍历处使用回溯,将已标记的岛屿撤销标记
//如果当前岛屿的下一个岛屿返回true也就是找到了,则可以返回了,不需要继续递归了
if( dfs(board, row-1, col, index) ||
dfs(board, row+1, col, index) ||
dfs(board, row, col-1, index) ||
dfs(board, row, col+1, index) == true) {
return true;
}
//回溯:这里是后序遍历执行代码,也就是说我们DFS一条ABC之后,会往回走一遍,也就是向父节点返回
//当往回走的时候,我们把当前节点值还原成原字符,因为后面再次查找路径的时候会使用该字符
board[row][col] = temp;
return false;
}
-
- 单词搜索(注意这里要判断下一个岛屿,不然超时)