前言
重点理解:一路向下,走到尽头再返回。的搜索顺序学会使用栈辅助以及递归两种形式实现树形,网格类结构的遍历,掌握节点访问标记的写法。
200:岛屿数量
题目要求:
给定一个二位网格grid,里面只有 '1'(陆地)和 '0'(水)
相连的陆地(上下左右)组成一个岛屿
要求:返回岛屿数量
核心思路
DFS深度优先搜索
具体流程:
- 遍历网格的每一个位置
- 遇到1;岛屿数+1
- 用DFS将与该陆地链接的所有相邻地区标记(将1变化为0)为访问过
代码实现
java
class Solution {
public int numIslands(char[][] grid) {
int rows=grid.length;
int cols=grid[0].length;
int count=0;
for(int i=0;i<rows;i++){
for(int j=0;j<cols;j++){
if(grid[i][j]=='1'){//找到新岛屿
count++;
dfs(grid,i,j);//淹掉
}
}
}
return count;
}
private void dfs(char[][] grid,int i,int j){
int rows=grid.length;
int cols=grid[0].length;
//遇到0或者出界就直接跳过
if(i<0||j<0||i>=rows||j>=cols||grid[i][j]=='0') return;
grid[i][j]='0';//标记为已经访问过
//上下左右方位继续dfs
dfs(grid,i+1,j);
dfs(grid,i-1,j);
dfs(grid,i,j-1);
dfs(grid,i,j+1);
}
}
总结
遍历网格,每当遇到1,计数就+1,然后通过dfs算法将所有链接在一起的岛屿一块淹掉。
最终返回count
695:岛屿的最大面积
题目要求:
给定一个二位网格grid,里面只有 '1'(陆地)和 '0'(水)
相连的陆地(上下左右)组成一个岛屿
要求:返回最大岛屿的面积(岛屿包含的陆地格子数)
核心思路
DFS深度优先搜素
- 遍历每一个格子
- 遇到1;调用dfs计算该岛屿面积
- 在dfs中:每访问到1,面积+1;将1修改为0;四个方向继续dfs
- 维护最大值
代码实现
java
class Solution {
public int maxAreaOfIsland(int[][] grid) {
int rows=grid.length;
int cols=grid[0].length;
int maxSize=0;
for(int i=0;i<rows;i++){
for(int j=0;j<cols;j++){
if(grid[i][j]==1){
int curSize=dfs(grid,i,j);
maxSize=Math.max(curSize,maxSize);
}
}
}
return maxSize;
}
private int dfs(int[][] grid,int i,int j){
int rows=grid.length;
int cols=grid[0].length;
if(i<0||j<0||i>=rows||j>=cols||grid[i][j]==0) return 0;
grid[i][j]=0;
int size=1;
size+=dfs(grid,i-1,j);
size+=dfs(grid,i+1,j);
size+=dfs(grid,i,j+1);
size+=dfs(grid,i,j-1);
return size;
}
}
总结
和上一题的区别就是需要额外记录岛屿的最大面积
通过观察:
发现变化的主要有dfs中面积的增加方式,主函数中最大值的维护方式
79:单词搜索
题目要求:给定一个 m×n 的字符网格 board,以及一个单词 word
判断 单词是否可以在网格中构成:
单词必须由相邻格子组成(上下左右,不允许斜对角)
同一个格子 不能重复使用
核心思路(DFS+递归)
遍历每一个格子
- 如果当前格子是单词的第一个字母-开始DFS
DFS递归 - 递归函数参数:坐标(i,j);当前单词索引k(表示正在匹配word[k])
- 终止条件:k==word.length即为true,越界/格子字符不匹配-false
- 递归过程:临时标记当前格子(如 board[i][j] = '#'),避免重复使用;四个方向dfs;回溯恢复原格子字符
- 如果任意一次dfs返回true,单词存在
代码实现
java
class Solution {
public boolean exist(char[][] board, String word) {
int rows = board.length;
int cols = board[0].length;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (dfs(board, word, i, j, 0)) {
return true;
}
}
}
return false;
}
private boolean dfs(char[][] board,String word,int i,int j,int index){
if(index==word.length())return true;//匹配成功
if(i<0||j<0||i>=board.length||j>=board[0].length||board[i][j]!=word.charAt(index)) return false;
char temp=board[i][j];//保存原值
board[i][j]='#';//标记访问过
boolean found=dfs(board, word, i-1, j, index+1)
|| dfs(board, word, i+1, j, index+1)
|| dfs(board, word, i, j-1, index+1)
|| dfs(board, word, i, j+1, index+1);
board[i][j]=temp;//回溯恢复
return found;
}
}
总结
都是DFS+回溯,本题的区别在于需要判断路径是否存在,返回布尔值
多了保存原值来保证回溯之前的结果