搜索算法系列之 DFS(二)

简介: 搜索算法系列之 DFS(二)

上一篇文章我们讲了 DFS 的理论部分,现在来看一道例题。

例子

剑指Offer 55 - I

二叉树的深度

题目:输入一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。

给定二叉树[3,9,20,null,null,15,7]

 3

  / \

 9  20

   /  \

  15   7

返回最大深度为 3。

这个题其实直接可以用层次遍历(BFS)解决,但 DFS 同样可以解决

思路

我们用 DFS分别遍历左右子树的深度,两者间取最大值即为此数的最大深度

当根节点为空时我们返回 0:

if(root==null) return0;

不为空的时候,我们遍历左子树的深度:

int leftDepth = maxDepth(root.left);

再遍历右子树的深度:

intrightDepth=maxDepth(root.right);

最后我们取左右子树深度的最大值:

returnMath.max(left+1, right+1); //因为root根节点算第一层,所以最后加1

代码

我们给出完整代码:

classSolution {

   publicintmaxDepth(TreeNoderoot) {

       if(root==null){

           return0;

       }

       intleft=maxDepth(root.left);

       intright=maxDepth(root.right);        

       returnMath.max(left+1, right+1);

   }

}

请注意:当节点不为空时,我们每次递归的maxDepth最后返回的是 Math.max(left + 1, right + 1) 而不是 0

上述代码也可以合并如下:

classSolution {

   publicintmaxDepth(TreeNoderoot) {

       if(root==null) return0;

       returnMath.max(maxDepth(root.left), maxDepth(root.right)) +1;

   }

}

剑指Offer 55 - II

平衡二叉树

题目:输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过 1,那么它就是一棵平衡二叉树。

示例 1:

给定二叉树 [3,9,20,null,null,15,7]

   3

  /\

 9  20

   /  \

  15   7

返回 true。

有了上一个题的基础,这个题思路很好想到。

思路

我们用上一题的 Depth 函数分别求出左右子树的深度

  • 并判断他们的差值是否小于等于 1(平衡条件)
  • 再判断左右子树分别是否满足平衡

满足上述条件,则整棵树平衡

代码

完整代码:

classSolution {

   publicbooleanisBalanced(TreeNoderoot) {

       if (root==null) returntrue;

       intgap=Math.abs(depth(root.left) -depth(root.right)); //左右子树深度差额绝对值

       return  gap<=1&&isBalanced(root.left) &&isBalanced(root.right);

   }

   privateintdepth(TreeNoderoot) {

       if (root==null) return0;

       returnMath.max(depth(root.left), depth(root.right)) +1;

   }

}

因为递归实现 DFS 比栈简洁方便,所以大部分 DFS 都是通过递归实现。

热完身下面我们开始来点正菜。

LeetCode 695

岛屿最大面积

题目:给定一个包含了一些 01 的非空二维数组 grid

一个岛屿是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。

找到给定的二维数组中最大的岛屿面积。(如果没有岛屿,则返回面积为 0 )

示例 1:

[[0,0,1,0,0,0,1,1],

[0,0,0,0,0,0,1,1],

[0,1,1,0,1,0,0,0]]

对于上边这个矩阵应返回 4(左上角)。

思路

我们考虑用DFS的思想,即从某块岛屿出发

  • 如果此块岛屿为 0(不是陆地),则跳过,开始遍历下一块岛屿
  • 如果此块岛屿为 1(是陆地),则计数器加 1 ,并开始遍历它的上下左右临近的岛屿,并将此块岛屿置 0 (保证每块陆地只被遍历一遍,避免重复遍历)

是 DFS 那么大可能离不开递归,此题我们首先定义出一个 dfs 的递归函数:

intdfs(int[][] grid, inti, intj);

参数为 grid 二维数组和 i , j 两个整数,那么 grid[i] [j] 即可遍历到某块岛屿。

我们考虑递归的边界条件,递归的边界条件应该是什么呢?即 grid[i] [j] 什么时候是非法的?

因为我们在遍历到某块陆地的时候,我们要紧接着递归遍历它的上下左右岛屿,考虑grid[i] [j]临近的上下左右的岛屿应该如何表示呢?

我们可以得出:

  • grid[i - 1] [j] 为上岛屿
  • grid[i + 1] [j] 为下岛屿
  • grid[i] [j - 1] 为左岛屿
  • grid[i] [j + 1] 为右岛屿

那么递归函数的参数什么时候非法呢?

i - 1j - 1 不能减到小于 0

  • 即当 i < 0j < 0非法

i + 1j + 1不能增大到超过数组大小

  • 即当 i == grid.lengthj == grid[i].length非法

并且当grid[i] [j] == 0 ,即此块岛屿不是陆地时返回 0

即:

if (i<0||j<0||i==grid.length||j==grid[i].length||grid[i][j] ==0)

           return0;

现在我们找到了dfs递归函数的边界。

按照最开始的算法思路,现在我们应该处理当当前岛屿为陆地时的情况:

  • 如果此块岛屿为 1(是陆地),则计数器加 1 ,并开始遍历它的上下左右临近的岛屿,并将此块岛屿置 0 (保证每块陆地只被遍历一遍,避免重复遍历)

当前岛屿若为 1 (为陆地),我们将这块陆地置为 0

并且递归遍历此块岛屿的上下左右临近岛屿,返回递归结果并加 1(计数器加 1)

即:

grid[i][j] =0;

returndfs(grid, i-1, j) +dfs(grid, i+1, j) +dfs(grid, i, j-1) +dfs(grid, i, j+1) +1;

此时,我们的递归函数内容就写完了。

我们回到主函数:

publicintmaxAreaOfIsland(int[][] grid);

主函数的内容就很好写了。

我们初始化一个变量为 0 (若给定矩阵全为 0 ,没有一块陆地,则返回 0):

intres=0;

dfs递归函数找出了每一部分陆地的面积大小,我们只需要在这些陆地当中,选取一个面积最大的即可:

Math.max(res, dfs(grid, i, j));

主函数里我们只需要两层 for 循环,来遍历二维数组对应的每个元素 :

for (inti=0; i<grid.length; i++) {

   for (intj=0; j<grid[i].length; j++) {

      ...

   }

}

代码

由上我们即写出了整个代码,贴出完整代码:

classSolution{

   publicintmaxAreaOfIsland(int[][] grid){

       intres=0;

       for (inti=0; i<grid.length; i++){

           for (intj=0; j<grid[i].length; j++){

               res=Math.max(res,dfs(grid,i,j));

           }

       }

       returnres;

   }

   privateintdfs(int[][] grid, inti, intj){

     if (i<0||j<0||i==grid.length||j==grid[i].length||grid[i][j] ==0)

           return0;

         grid[i][j] =0;

     returndfs(grid, i-1, j) +dfs(grid, i+1, j) +dfs(grid, i, j-1) +             dfs(grid, i, j+1) +1;

   }    

}

这是一道 Medium 题目

其实理解了 dfs 递归的思想,找到了递归函数的边界,再结合题目本身的条件,其实不难做出来。

那今天的内容就先到这里啦~


目录
相关文章
|
24天前
|
存储 算法 Java
Java中,树与图的算法涉及二叉树的前序、中序、后序遍历以及DFS和BFS搜索。
【6月更文挑战第21天】Java中,树与图的算法涉及二叉树的前序、中序、后序遍历以及DFS和BFS搜索。二叉树遍历通过访问根、左、右子节点实现。DFS采用递归遍历图的节点,而BFS利用队列按层次访问。以下是简化的代码片段:[Java代码略]
22 4
|
13天前
|
数据采集 算法 JavaScript
揭开JavaScript字符串搜索的秘密:indexOf、includes与KMP算法
JavaScript字符串搜索涵盖`indexOf`、`includes`及KMP算法。`indexOf`返回子字符串位置,`includes`检查是否包含子字符串。KMP是高效的搜索算法,尤其适合长模式匹配。示例展示了如何在数据采集(如网页爬虫)中使用这些方法,结合代理IP进行安全搜索。代码示例中,搜索百度新闻结果并检测是否含有特定字符串。学习这些技术能提升编程效率和性能。
揭开JavaScript字符串搜索的秘密:indexOf、includes与KMP算法
|
4天前
|
机器学习/深度学习 数据采集 算法
Python实现GBDT(梯度提升树)分类模型(GradientBoostingClassifier算法)并应用网格搜索算法寻找最优参数项目实战
Python实现GBDT(梯度提升树)分类模型(GradientBoostingClassifier算法)并应用网格搜索算法寻找最优参数项目实战
|
4天前
|
机器学习/深度学习 数据采集 算法
Python实现SSA智能麻雀搜索算法优化支持向量机回归模型(SVR算法)项目实战
Python实现SSA智能麻雀搜索算法优化支持向量机回归模型(SVR算法)项目实战
|
4天前
|
机器学习/深度学习 数据采集 算法
Python实现SSA智能麻雀搜索算法优化支持向量机分类模型(SVC算法)项目实战
Python实现SSA智能麻雀搜索算法优化支持向量机分类模型(SVC算法)项目实战
|
5天前
|
机器学习/深度学习 人工智能 分布式计算
算法金 | 最难的来了:超参数网格搜索、贝叶斯优化、遗传算法、模型特异化、Hyperopt、Optuna、多目标优化、异步并行优化
机器学习中的超参数调优是提升模型性能的关键步骤,包括网格搜索、随机搜索、贝叶斯优化和遗传算法等方法。网格搜索通过穷举所有可能的超参数组合找到最优,但计算成本高;随机搜索则在预设范围内随机采样,降低计算成本;贝叶斯优化使用代理模型智能选择超参数,效率高且适应性强;遗传算法模拟生物进化,全局搜索能力强。此外,还有多目标优化、异步并行优化等高级技术,以及Hyperopt、Optuna等优化库来提升调优效率。实践中,应结合模型类型、数据规模和计算资源选择合适的调优策略。
10 0
算法金 | 最难的来了:超参数网格搜索、贝叶斯优化、遗传算法、模型特异化、Hyperopt、Optuna、多目标优化、异步并行优化
|
10天前
|
算法
基于Dijkstra算法的最优行驶路线搜索matlab仿真,以实际城市复杂路线为例进行测试
使用MATLAB2022a实现的Dijkstra算法在城市地图上搜索最优行驶路线的仿真。用户通过鼠标点击设定起点和终点,算法规划路径并显示长度。测试显示,尽管在某些复杂情况下计算路径可能与实际有偏差,但多数场景下Dijkstra算法能找到接近最短路径。核心代码包括图的显示、用户交互及Dijkstra算法实现。算法基于图论,不断更新未访问节点的最短路径。测试结果证明其在简单路线及多数复杂城市路况下表现良好,但在交通拥堵等特殊情况下需结合其他数据提升准确性。
|
24天前
|
存储 算法 Java
Java查找算法概览:二分查找适用于有序数组,通过比较中间元素缩小搜索范围;哈希查找利用哈希函数快速定位,示例中使用HashMap存储键值对,支持多值关联。
【6月更文挑战第21天】Java查找算法概览:二分查找适用于有序数组,通过比较中间元素缩小搜索范围;哈希查找利用哈希函数快速定位,示例中使用HashMap存储键值对,支持多值关联。简单哈希表实现未涵盖冲突解决和删除操作。
19 1
|
5天前
|
机器学习/深度学习 数据采集 自然语言处理
Python实现支持向量机SVM分类模型(SVC算法)并应用网格搜索算法调优项目实战
Python实现支持向量机SVM分类模型(SVC算法)并应用网格搜索算法调优项目实战
|
5天前
|
机器学习/深度学习 数据采集 算法
Python实现人工神经网络回归模型(MLPRegressor算法)并基于网格搜索(GridSearchCV)进行优化项目实战
Python实现人工神经网络回归模型(MLPRegressor算法)并基于网格搜索(GridSearchCV)进行优化项目实战