给你一个由
'1'
(陆地)和'0'
(水)组成的的二维网格,请你计算网格中岛屿的数量。岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
示例 1:
输入:grid = [ ["1","1","1","1","0"], ["1","1","0","1","0"], ["1","1","0","0","0"], ["0","0","0","0","0"] ] 输出:1示例 2:
输入:grid = [ ["1","1","0","0","0"], ["1","1","0","0","0"], ["0","0","1","0","0"], ["0","0","0","1","1"] ] 输出:3提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 300
grid[i][j]
的值为'0'
或'1'
深度优先遍历可用于树,图,或者网格中,
图的深度优先遍历 从初始的访问结点出发,初始访问结点可能有多个邻接结点,首先访问第一个邻接结点,然后再以这个被访问的邻接结点作为初始结点,访问它的第一个邻接结点,每次访问完当前结点之后首先访问当前节点的第一个邻接结点,这种策略是优先纵向深入。是一个递归的过程
1.首先访问初始结点,(做这个算法问题的判断),并将这个节点标记为已访问,防止重复判断。
2.查找结点的第一个邻接结点,若存在,则对当前结点进行深度优先遍历,(即根据当前算法问题做出判断),然后继续查找这个结点的第一个邻接结点,进行深度优先遍历,如果不存在,则退回到上一个结点,继续查找这个结点的另一个邻接结点,从当前结点向下搜索。
判断图的终止条件为当前结点没有邻接结点
使用邻接矩阵深搜
框架代码
class Grape{
public ArrayList vertex; //存储顶点的合集
public int[][] edges; //邻接矩阵
public int edgeNum; //边数
public boolean[] isVisited; //记录当前顶点是否当问过
//图的深度优先遍历框架
public void frame(){
isVisited = new boolean[vertex.size()];//初始化判断数组
//开始遍历图的每一个顶点 对每个结点都进行深搜
for(int i = 0;i < vertex.size();i++){
if (isVisited[i]){
//如果当前顶点已经访问过,则跳过访问下一个
continue;
}else{
dfs(i);//遍历
}
}
}
public void dfs(int i){
//省略 每个算法问题在此处进行判断
isVisited[i] =true;//将当前结点设置为已访问
int n = getFirst(i);//找出当前结点的第一个邻接结点
if (n != -1){//当前结点还有未访问的邻接结点
dfs(n);
}else {
return;
}
}
//找当前结点的邻接结点 (通过邻接结点)
private int getFirst(int i) {
//遍历其他结点
for(int j=0;j0&&!isVisited[j]) {
//返回这个结点
return j;
}
}
return -1;
}
}
树的深度优先遍历类似,从根节点开始遍历,然后再去判断当前树的左树,然后将当前左树作为根节点,继续判断当前节点的左子树,知道遍历到左子树尽头,然后退回到上一个结点,判断右子树
终止条件为当前根节点为空
框架代码
void dfs(TreeNode root) {
// 判断条件
if (root == null) {
return;
}
// 访问两个结点:左子结点、右子结点
dfs(root.left);
dfs(root.right);
}
网格的深度优先遍历 类似 找出终止条件 和 判断方向
网格的终止条件就是不能遍历到的位置也就是越界的地方 网格有四个运动方向上下左右 如果超出了网格的范围就退回去 网格也需要判断是否重复遍历 遍历每一个结点之后做标记 如果已经访问过就不再访问
框架代码
void dfs(int[][] grid, int r, int c) {
// 判断终止条件
// 如果坐标 (r, c) 超出了网格范围,直接返回
if (!inArea(grid, r, c)) {
return;
}
// 访问上、下、左、右四个相邻结点
dfs(grid, r - 1, c);
dfs(grid, r + 1, c);
dfs(grid, r, c - 1);
dfs(grid, r, c + 1);
}
// 判断坐标 (r, c) 是否在网格中
boolean inArea(int[][] grid, int r, int c) {
return 0 <= r && r < grid.length
&& 0 <= c && c < grid[0].length;
}
本题为网格的深度优先遍历 深搜每结束一次 说明已经遍历完一个岛屿计数
public int numIslands(char[][] grid) {
int res = 0;
//遍历结点 从当前结点开始遍历
for (int i = 0;i < grid.length;i++){
for (int j = 0;j < grid[0].length;j++){
//如果当前结点是岛屿就开始遍历
if (grid[i][j] == '1'){
dfs(grid,i,j);
//计数
res++;
}
}
}
return res;
}
public void dfs(char[][] grid,int row,int col){
//终止条件判断
if (row < 0 || row >= grid.length || col < 0 || col >= grid[0].length){
return;
}
//判断当前结点是都已经被判断
if (grid[row][col] != '1'){
return;
}
//将当前位置设置为已经访问过
grid[row][col] = 2;
//上下左右遍历
dfs(grid,row - 1,col);
dfs(grid,row + 1,col);
dfs(grid,row,col - 1);
dfs(grid,row,col + 1);
}