算法【Java】—— 二叉树的深搜

深搜

深搜简单来说就是一直递归到底,然后返回,以二叉树为例,就是从根节点出发一直搜索到叶子节点,然后想上返回。

在这里插入图片描述

这里简单说明一下:深搜的英文缩写是 dfs,下面定义深搜函数名我直接命名为 dfs

实战演练

计算布尔二叉树的值

https://leetcode.cn/problems/evaluate-boolean-binary-tree/description/

在这里插入图片描述

看到二叉树的题目,大家应该都会首选递归来解决,现在我们来思考如何递归:

首先分解主问题,要想求出二叉树布尔值,首先要知道左子树和右子树的布尔值,再通过根节点进行布尔运算

如何得到左右子树的布尔值,还是一样,根据上面的操作,那么我们就完成了问题的拆分,成功获得了子问题,函数的参数是需要根节点即可。

最后我们来看一下递归的出口,当我们遇到的节点为0 / 1 时,我们直接返回 false / true 即可。

回顾上面的递归操作,从根节点一直递归到叶子节点,这就是深搜。

class Solution {public boolean evaluateTree(TreeNode root) {if(root.val == 1) return true;else if(root.val == 0) return false;boolean left = evaluateTree(root.left);boolean right = evaluateTree(root.right);return root.val == 2 ? left | right : left & right;}
}

求根节点到叶节点数字之和

https://leetcode.cn/problems/sum-root-to-leaf-numbers/

在这里插入图片描述

找出子问题:要想求出根节点到叶子节点的数字之和,需要知道左子树和右子树的数字之和,然后进行相加,就可以得出答案,要想求出左右子树的数字之和,还是按照上面的操作。

现在我们来分析函数参数的设计,首先根节点是一定要知道的,其次就是前面得到的数字之和,有了前面的数字之和我们就可以计算当前节点的数字之和:
在这里插入图片描述
就像上图所示,当递归到 5 这个节点的时候,我们需要获取到前面的 49, 然后计算得到目前节点的数值 49 * 10 + 5 = 495

我们先看代码:

class Solution {public int sumNumbers(TreeNode root) {return dfs(root, 0);}int dfs(TreeNode root, int sum) {sum = sum * 10 + root.val;int count = 0;if(root.left != null) count += dfs(root.left, sum);if(root.right != null) count += dfs(root.right, sum);return count == 0 ? sum : count;}
}

你会发现我这里没有设计函数的出口,为什么?首先题目的节点个数是大于等于 1 的,所以我们在进行递归的时候,如果发现不存在左子树就不用进去,不存在右子树也不用进去,这其实就是剪枝的思想,既然我们不会进到空节点,也就没有 节点为空的情况,自然不需要再前面加递归的出口。

然后就是先计算当前节点的数字之和,接着获取左子树和右子树的数字之和,最后返回两者之和即可。

这里要注意 count 这个变量,因为初始状态设置为 零,所以当我们遇到叶子节点的时候,是不会进行左右子树的搜索的,这时候就不能直接返回 count ,而是返回这个节点的数字之和。

二叉树剪枝

https://leetcode.cn/problems/binary-tree-pruning/description/

在这里插入图片描述

我们进行深搜的时候,什么时候进行剪枝?当发现根节点的左边和右边都为空并且根节点的数值为 0 的时候,需要裁剪,那么函数需要传递的参数就是根节点。

函数体的设计:首先我们要得到根节点左右子树是否为空,那么需要进行递归,先看看左子树是否需要裁剪,再看看右子树是否需要裁剪,最后根据前面我们得到的条件来判断是否需要进行根节点的裁剪。

递归出口:当节点为空,直接返回。

class Solution {public TreeNode pruneTree(TreeNode root) {if(root == null) {return root;}root.left = pruneTree(root.left);root.right = pruneTree(root.right);if(root.val == 0 && root.left == null && root.right == null) {return null;} return root;}
}

验证二叉搜索树

https://leetcode.cn/problems/validate-binary-search-tree/description/

在这里插入图片描述

首先我们知道二叉树搜索树中序遍历会得到一个有序的数据,所以我们可以利用这一个特性来解决这个问题。

首先深搜使用的是中序遍历,参数为根节点,然后我们需要一个全局变量来记录上一个节点的数值

这里直接上代码:

class Solution {long prev = Long.MIN_VALUE;public boolean isValidBST(TreeNode root) {if(root.left != null && !isValidBST(root.left)) return false;if(root.val > prev) {prev = root.val;} else {return false;}if(root.right != null && !isValidBST(root.right)) return false;return true;}
}

当我们知道左子树已经不是二叉搜索树的时候,我们就不需要进行后面的操作,直接返回false,这就是剪枝的思想。

这里要注意由于二叉树最小数值可能为 2 ^ -31,所以我们设置 prev 全局变量的时候,要使用 Long.MIN_VALUE。

二叉搜索树中第 k 小的元素

https://leetcode.cn/problems/kth-smallest-element-in-a-bst/description/

在这里插入图片描述

这里定义两个全部变量,一个记录当前是否为第 k 小,一个记录当前获得的数值。

之后进行中序遍历,当 count == 0 时直接返回答案。

这里要注意当左子树不为空,才进行深搜,右子树同理。

class Solution {int prev = 0;int count = 0;public int kthSmallest(TreeNode root, int k) {count = k;return dfs(root);}int dfs(TreeNode root) {if(count == 0) {return prev;}if(root.left != null) {dfs(root.left);}if(count == 0) {return prev;} else {prev = root.val;count--;}if(root.right != null) {dfs(root.right);}return prev;}
}

二叉树的所有路径

https://leetcode.cn/problems/binary-tree-paths/description/

在这里插入图片描述

这里我们使用 StringBuffer 来作为参数,因为 String 进行频繁的插入是很慢的。

定义全部变量 ans ,进行链表的接收。

注意在深搜函数中我们不能直接修改 参数 _path,因为这是一个引用变量,你的修改是真的会影响到这个 path的,所以这里采用新建立一个 path

函数递归流程:首先先拼接当前节点的数值,然后检查该节点是否为叶子节点,如果是,则直接返回链表,如果不是则需要添加一个 ->,然后进行左子树和右子树的深搜,这里我采用剪枝的思想,只用左右子树存在的时候才进行深搜,所以没有递归出口 root == null 这种情况的出现。

class Solution {List<String> ans = new ArrayList<>();public List<String> binaryTreePaths(TreeNode root) {return dfs(root, new StringBuffer());}List<String> dfs(TreeNode root, StringBuffer _path) {StringBuffer path = new StringBuffer(_path);path.append(root.val);if(root.left == null && root.right == null) {ans.add(path.toString());return ans;}path.append("->");if(root.left != null) {dfs(root.left,path);}if(root.right != null) {dfs(root.right,path);}return ans;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/54399.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

内存占用估算方法

优质博文&#xff1a;IT-BLOG-CN 通过掌握每种数据类型的大小&#xff0c;就可以更准确地预测对象和数据的内存消耗。 一、基础数据类型 Java基础数据类型结构&#xff0c;在64位系统开启指针压缩情况下的内存占用字节数&#xff1a; booleanbytecharshortintlongfloatdoub…

PYTHON实现HTTP request的一些有用的函数

前言 我们知道&#xff0c;当需要设计一个程序和服务器进行交互时&#xff0c;往往会用到HTTP的request&#xff0c;即服务器有一个对外接口REST API&#xff0c;因此当向服务器发送符合格式要求的HTTP request时&#xff0c;服务器会给出响应&#xff0c;甚至执行一些任务。如…

码随想录算法训练营第62天|卡码网:97. 小明逛公园、127. 骑士的攻击

1. 卡码网 97. 小明逛公园 题目链接&#xff1a;https://kamacoder.com/problempage.php?pid1155 文章链接&#xff1a;https://www.programmercarl.com/kamacoder/0097.小明逛公园.html 思路&#xff1a; 使用Floyd 算法&#xff0c;目的是解决多源最短路问题&#xff0c;即 …

如何编写一个优雅的commit message

在Git中&#xff0c;git commit 命令扮演着至关重要的角色。它的主要作用是将暂存区&#xff08;staging area&#xff09;里的改动内容提交到本地仓库&#xff08;repository&#xff09;中&#xff0c;形成一个新的版本或提交&#xff08;commit&#xff09;。这个过程是 Git…

基于Node2Vec的图嵌入实现过程

目录 一、引言二、Node2Vec&#xff08;原理&#xff09;2.1 随机游走&#xff08;Random Walk&#xff09;2.2 嵌入学习2.3 Node2Vec 的优势 三、使用 Node2Vec 进行图嵌入&#xff08;实践&#xff09;3.1 读取和转换 JSON 文件为 Graph 对象3.2 训练 Node2Vec 模型3.3 二维嵌…

10款好用的开源 HarmonyOS 工具库

大家好&#xff0c;我是 V 哥&#xff0c;今天给大家分享10款好用的 HarmonyOS的工具库&#xff0c;在开发鸿蒙应用时可以用下&#xff0c;好用的工具可以简化代码&#xff0c;让你写出优雅的应用来。废话不多说&#xff0c;马上开整。 1. efTool efTool是一个功能丰富且易用…

Kotlin:2.0.20 的新特性

一、概述 Kotlin 2.0.20英文版官方文档 Kotlin 2.0.20发布了!这个版本包括对Kotlin 2.0.0的性能改进和bug修复&#xff0c;我们在其中宣布Kotlin K2编译器为Stable。以下是本次发布的一些亮点: 数据类复制函数将具有与构造函数相同的可见性来自默认目标层次结构的源集的静态访…

Python批量下载PPT模块并实现自动解压

日常工作中&#xff0c;我们总是找不到合适的PPT模板而烦恼。即使有免费的网站可以下载&#xff0c;但是一个一个地去下载&#xff0c;然后再批量解压进行查看也非常的麻烦&#xff0c;有没有更好方法呢&#xff1f; 今天&#xff0c;我们利用Python来爬取一个网站上的PPT&…

HTML+CSS基础用法介绍五

目录&#xff1a; 结构伪类选择器盒子模型-边框线盒子模型-内边距盒子模型-解决盒子被撑大盒子模型-外边距与版心居中小知识&#xff1a;清除浏览器中所有标签的默认样式内容溢出控制显示方式盒子模型-圆角 &#x1f40e;正片开始 结构伪类选择器 什么是结构伪类选择器&…

全新一区PID搜索算法+TCN-LSTM+注意力机制!PSA-TCN-LSTM-Attention多变量时间序列预测(Matlab)

全新一区PID搜索算法TCN-LSTM注意力机制&#xff01;PSA-TCN-LSTM-Attention多变量时间序列预测&#xff08;Matlab&#xff09; 目录 全新一区PID搜索算法TCN-LSTM注意力机制&#xff01;PSA-TCN-LSTM-Attention多变量时间序列预测&#xff08;Matlab&#xff09;效果一览基本…

66 使用注意力机制的seq2seq_by《李沐:动手学深度学习v2》pytorch版

系列文章目录 文章目录 系列文章目录动机加入注意力总结代码定义注意力解码器训练小结练习 我们来真的看一下实际应用中&#xff0c;key&#xff0c;value&#xff0c;query是什么东西&#xff0c;但是取决于应用场景不同&#xff0c;这三个东西会产生变化。先将放在seq2seq这个…

Linux dlsym符号查找疑惑分析

dlsym 函数是 Linux 下动态链接库&#xff08;shared library&#xff09;编程中的一个重要函数。它用于在运行时获取动态链接库中符号的地址&#xff0c;通常用于获取函数指针或变量的地址。 以下是 dlsym 函数的基本用法和示例。 1. 函数原型 void *dlsym(void *handle, c…

如何实现事件流操作

文章目录 1 概念介绍2 使用方法3 示例代码我们在上一章回中介绍了通道相关的内容,本章回中将介绍StreamProvider组件.闲话休提,让我们一起Talk Flutter吧。 1 概念介绍 在Flutter中Stream是经常使用的组件,对该组件的监听可void main() {///让状态栏和程序的appBar融为一体…

海龟绘图画小汽车

1、效果图&#xff1a; 2、完整代码 import turtlet turtle.Turtle() #创建一个新的画布对象t.penup() t.goto(0,80) t.pendown()t.fillcolor("red") t.begin_fill() t.lt(180) t.fd(60) t.lt(45) t.fd(113) t.rt(45) t.fd(80) t.lt(90) t.fd(80) t.…

常见的VPS或者独立服务器的控制面板推荐

随着越来越多的企业和个人转向VPS和独立服务器以获得更高的性能和灵活性&#xff0c;选择合适的控制面板变得尤为重要。一个好的控制面板可以大大简化服务器管理&#xff0c;提高工作效率。本篇文章将介绍2024年最值得推荐的VPS控制面板&#xff0c;帮助您做出明智的选择。 1.…

论文阅读(十一):CBAM: Convolutional Block Attention Module

文章目录 IntroductionConvolutional Block Attention ModuleExperimentsConclusion 论文题目&#xff1a;CBAM: Convolutional Block Attention Module&#xff08;CBAM&#xff1a;卷积注意力机制&#xff09;   论文链接&#xff1a;点击跳转   代码链接&#xff1a;Git…

关于BSV区块链覆盖网络的常见问题解答(上篇)

​​发表时间&#xff1a;2024年9月20日 在BSV区块链上的覆盖网络服务为寻求可扩展、安全、高效交易处理解决方案的开发者和企业家开辟了新的视野。 作为开创性的曼达拉升级的一部分&#xff0c;覆盖网络服务提供了一个强大的框架&#xff0c;用于管理特定类型的交易和数据访问…

新编英语语法教程

新编英语语法教程 1. 新编英语语法教程 (第 6 版) 学生用书1.1. 目录1.2. 电子课件 References A New English Grammar Coursebook 新编英语语法教程 (第 6 版) 学生用书新编英语语法教程 (第 6 版) 教师用书 1. 新编英语语法教程 (第 6 版) 学生用书 https://erp.sflep.cn/…

3.点位管理改造-列表查询——帝可得管理系统

目录 前言一、与页面原型差距1.现在&#xff1a;2.目标&#xff1a;3. 存在问题&#xff1a; 二、修改1.重新设计SQL语句2.修改mapper层&#xff0c;使用Mybatis中的嵌套查询3.修改service层4. 修改controller层5.前端修改6.补充区域查看详情7.数据完整性 前言 提示&#xff1…

《OpenCV 计算机视觉》—— 视频背景建模

文章目录 一、背景建模的目的二、背景建模的方法三、背景建模的步骤四、注意事项五、代码实现 一、背景建模的目的 视频背景建模的主要目的是从视频序列中提取出静态背景&#xff0c;以便将动态的前景对象与静态的背景进行分离。这有助于进一步分析和处理视频内容&#xff0c;…