dfs
dfs 递归模板
dfs 的思想就像是二叉树的先序遍历。
public void solve(char[][] grid) {
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) {
if (grid[i][j] == ?)
dfs(grid, i, j);
}
}
void dfs(char[][] grid, int i, int j) {
if (判边界 || 额外条件) {
return;
}
具体额外的操作...
dfs(grid, i - 1, j); // 上
dfs(grid, i + 1, j); // 下
dfs(grid, i, j - 1); // 左
dfs(grid, i, j + 1); // 右
某些操作的回溯...
}
dfs 非递归模板
非递归 dfs 一般用 stack,一般用非递归都需要一种辅助类 Pos 来记录结点的横纵坐标,甚至可能需要增加其他状态遍历记录某个结点的价值。
//主方法
public int solve(char[][] grid) {
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) {
if (grid[i][j] == ?)
dfs(grid, i, j);
}
}
//深搜
void dfs(char[][] grid, int i, int j) {
stack.push(new Pos(i, j));
额外操作...
while( !stack.isEmpty() ) {
...
stack.peek();
int u, d, l, r; // 上、下、左、右
if(u >= 0 && 附加条件) {
stack.push(new Pos(u, currPos.j));
continue;
}
...
stack.pop();
}
}
bfs
bfs 非递归
dfs 和 dfs 不同的是,dfs 中搜索 u, d, l, r,只要搜索到一个满足条件,dfs 就顺着该方向继续搜索,所以你可以看到 dfs 代码中,只要满足条件,就入 Stack,然后 continue 本次搜索,进行下一次搜索。
bfs 中,我们要把上下左右满足条件的都入队,所以搜索的时候就不能 continue。
public void solve(char[][] grid) {
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) {
if (grid[i][j] == ?)
bfs(grid, i, j);
}
}
void bfs(char[][] grid, int i, int j) {
queue.add(new Pos(i, j));
while (!queue.isEmpty()) {
Pos pos = queue.poll();
for (int k = 0; k < 4; k++) { //搜索四个方向合适的结点
if (判边界 && grid[newX][newY] == 1)
queue.add(new Pos(newX, newY, pos.minute + 1));
}
}
}
练手题目
- 黄金矿工
- 岛屿数量
- 岛屿的最大面积
- 统计封闭岛屿的数目
- 岛屿的周长
- 被环绕的区域
- 蓝桥杯的迷宫路径
- 朋友圈
- 飞地的数量
- 「图像渲染」