【递归、搜索与回溯】搜索

搜索

  • 1.计算布尔二叉树的值
  • 2.求根节点到叶节点数字之和
  • 3. 二叉树剪枝
  • 4.验证二叉搜索树
  • 5.二叉搜索树中第K小的元素
  • 6.二叉树的所有路径

在这里插入图片描述

点赞👍👍收藏🌟🌟关注💖💖
你的支持是对我最大的鼓励,我们一起努力吧!😃😃

1.计算布尔二叉树的值

题目链接:2331. 计算布尔二叉树的值

题目分析:

在这里插入图片描述

给一颗完整二叉树,孩子节点要么是0要么是2,不存在1个孩子节点。
叶子节点和非叶子节点数字分别代表不同的意思,最后将root根结果bool值返回去。

在这里插入图片描述
算法原理:

解法:递归
宏观角度看待递归
当想知道root根节点bool值时,我要先知道左子树bool值,在知道右子树bool值,然后将左右子数的bool值和root本身信息做整合。当我们要知道左子树和右子树的bool值,你会发现它和大问题是一样的。大问题是解决整棵树的bool值,小问题是解决左子树bool值,右子树bool值。此时把左指针传给dfs,dfs把左子树bool值给你,把右指针传给dfs,dfs把右子树bool值给你。所以dfs非常好设计。
函数头
bool dfs(TreeNode* root)

在这里插入图片描述
函数体也就出来了,先求左子树bool值,在求右子树bool,不要管递归如何执行,只需要知道你给它数据它一定能完成任务。
bool left=dfs(root->left)
bool right=dfs(root->right)
最后在将左子树和右子树bool值和root做整合。

递归出口 到叶子节点就不需要往后递归了,此时返回结果就行了

class Solution {
public:bool evaluateTree(TreeNode* root) {if(root->left == nullptr) return root->val == 0 ? false : true;bool left=evaluateTree(root->left);bool right=evaluateTree(root->right);return root->val == 2 ? left|right : left&right;}
};

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

题目链接:129. 求根节点到叶节点数字之和

题目分析:

在这里插入图片描述

将根到叶子节点组合的数加起来

在这里插入图片描述

算法原理:

解法:递归
首先我们要找到相同子问题,在树中相同子问题很好找,只需要关注递归到每一层需要干什么事情即可。当它们干的都是一样的事情,这就是相同的子问题。

当递归到5这一层,我发现要拿到和5相连下面的叶子节点的数把它们加起来,然后返回给根节点。当到5这一层

  1. 首先要把12先给我传过来,不然我怎么算出1258,也就是到某一层要把它之前路径上之后给我传过来。然后拿到这个12,先算出125。
  2. 然后把125传给左边
  3. 把125传给右边
  4. 然后把左边值的和与右边值的和相加,然后返回上一层节点

在这5这一层要完成4个任务,同理其他层也是要完成相同的任务。

在这里插入图片描述

1.函数头
首先要有一个返回值,就是传给dfs一个根节点把和它相连的叶子节点的和返回。但是要注意的是,我们除了要传一个根节点,还需要再把递归到该层的上面路径和拿到! 因此函数头是int dfs(root,presum)

2.函数体
1、2、3、4个步骤

3.递归出口
当到叶子节点就可以返回了,但是要注意的是,这个递归出应该在步骤1之后的,因为到叶子节点也要把叶子节点的数加上才向上返回的。

class Solution {
public:int sumNumbers(TreeNode* root) {return dfs(root,0);}int dfs(TreeNode* root,int presum){presum=presum*10+root->val;if(root->left == nullptr && root->right == nullptr)return presum;int ret=0;if(root->left) ret+=dfs(root->left,presum);if(root->right) ret+=dfs(root->right,presum);return ret;}
};

3. 二叉树剪枝

题目链接:814. 二叉树剪枝

题目分析:

在这里插入图片描述

注意这里的剪枝和前面说的剪枝是不一样的,前面的是那条路不是通往终点的路不能在走了,这里的剪枝真的就是把分枝剪掉!

返回移除了所有 不包含 1 的子树 的原二叉树 的意思是,就是如果子树全是0就把它剪掉。如果子数既有1又有0就不能剪掉。
在这里插入图片描述

算法原理:

通过决策树,抽象出递归的三个核心问题
也就是说通过,完成二叉树剪枝这个任务,完成递归三个核心问题。
像之前先把每个子问题要完成任务先找到,但是有时候某些道题非常麻烦,无法总结出子问题到底干了什么问题,这道题是给一个根节点然后把子树全为0剪掉然后把新根节点返回来。但是有些题特别抽象你根本无法总结出来你让这个递归去完成什么任务,任务太多了。此时我们要有一个能力,通过研究递归的过程来总结出函数头、函数体、递归出口!

在这里插入图片描述

首先这肯定是一个后序遍历,先要确定左右子树是什么情况才能决定是否把这个子树干掉。

当作后序遍历到底最左节点,然后再后序发现它左为空右为空,然后自己本身也是0,说明可以给它剪枝。然后回到上一层但是有一个问题,是不是要修改上一层左子树的指针啊,因此这个递归函数要有一个返回值 TreeeNode*。
在这里插入图片描述
然后如果左右子树都为空,但自己是1,说明不能剪枝
在这里插入图片描述
当我们把根左子树都弄好了,其实整个递归过程就出来。
在这里插入图片描述

  1. 函数头
    TreeNode* dfs(root) 给一个根节点,然后把结果给我
  2. 函数体
    左子树右子树都搞完返回给我一个东西,然后通过返回值在结合我自己看是否需要把自己删除。
    1.左子树、2.右子树、 3.判断
  3. 递归出口
    遇到null结束,就返回null
class Solution {
public:TreeNode* pruneTree(TreeNode* root) {if(root == nullptr) return nullptr;root->left=pruneTree(root->left);root->right=pruneTree(root->right);if(root->left == nullptr && root->right == nullptr && root->val == 0)return nullptr;else return root;}
};

4.验证二叉搜索树

题目链接:98. 验证二叉搜索树

题目描述:

在这里插入图片描述

算法原理:
这道题主要想说的有三个方面 1. 全局变量的优势 ,2. 回溯 ,3. 剪枝

这里我们利用一个性质,二叉搜索树的中序遍历结果,是一个有序的序列
可能你会想到用一个数组记录中序遍历的结果,然后在遍历一下数组。但是这样空间开销太大了。

我们还是利用这个性质解决这个问题,但是我们可以仅用一个全局变量就来判断这个中序遍历是否是有序的。这个全局变量是在中序遍历中当我遍历到某一个位置它的前序是多少。 并且因为是全局的,并不需要考虑在递归中如何传递,直接拿过来用就可以了!
在这里插入图片描述

当中序遍历到第一个节点后,比较该值和prev的大小,当前这个值比无穷小大说明当前中序遍历是有序的,就更新prev等于这个值。然后向上传,同理依旧是拿这个值和prev做比较等等,知道中序遍历到19发现这个值比prev要小,此时中序遍历就不是有序的,说明30左子树就不一颗二叉搜索树,也说明20右子树不是一颗二叉搜索树,进而说明整棵树就不是一颗二叉搜索树。直接返回即可!

在这里插入图片描述

所以这道题我们可以借助全局变量和中序遍历就可以解决这个问题。
我们有两种策略判断它是否是一个二叉树。
策略一:

  1. 左子树是一颗二叉搜索树,
  2. 当前节点也要符合二叉搜索树的定义
  3. 右子树也是一颗二叉搜索树

此时就颗树就是一颗二叉搜索树!

一个递归99%都有回溯,往上层返回就是回溯!
在这里插入图片描述

当前节点值的范围正好有INT_MIN,如果我们prev=INT_MIN 有可能第一层判断就有问题。因此把prev类型换一下,long 或者 long long

在这里插入图片描述

class Solution {
public:long prev=LONG_MIN;bool isValidBST(TreeNode* root) {if(root == nullptr) return true;bool left=isValidBST(root->left);bool cur=false;if(root->val > prev){prev=root->val;cur=true;}bool right=isValidBST(root->right);return left && cur && right;}
};

策略二:剪枝

当判断某棵子树不是二叉搜索树,整体就已经不是二叉搜索树了,就没有必要在去其他子树递归了,直接返回结果就行了。加快了我们的搜索过程
在这里插入图片描述
剪枝其实很简单,不要想的那么复杂。

class Solution {
public:long prev=LONG_MIN;bool isValidBST(TreeNode* root) {if(root == nullptr) return true;bool left=isValidBST(root->left);//剪枝if(left == false) return false;bool cur=false;if(root->val > prev){prev=root->val;cur=true;}//剪枝if(cur == false) return false;bool right=isValidBST(root->right);return left && cur && right;}
};

5.二叉搜索树中第K小的元素

题目链接:230. 二叉搜索树中第K小的元素

题目描述:

在这里插入图片描述

算法原理:

有了上面题的基础,这道题就非常简单了,仅需两个全局变量+中序遍历就行了

每次count-1,直到count==0,用ret记录结果。找到最终结果此时其他子树也不用遍历。也可以使用剪枝。

在这里插入图片描述

如果不使用全局遍历,就需要在递归函数中传参,并且还需要考虑参数在递归函数中如何改变。

class Solution {int count=0,ret=0;
public:int kthSmallest(TreeNode* root, int k) {count=k;dfs(root);return ret;// if(root == nullptr) return 0;// if(count <= k)//     kthSmallest(root->left,k);// ++count;// if(count == k)// {//     ret=root->val;// }// if (count <= k)//     kthSmallest(root->right,k);// return ret;}void dfs(TreeNode* root){if(root == nullptr || count == 0) return;dfs(root->left);--count;if(count == 0) ret=root->val;dfs(root->right);}
};

6.二叉树的所有路径

题目链接:257. 二叉树的所有路径

题目分析:

在这里插入图片描述

题目很简单,让找根到叶子节点的所有路径。

算法原理:
这道题重点强调的还是

  1. 全局变量
  2. 回溯
  3. 剪枝

其中这道题最重要的是想说回溯 ----> “恢复现场” ,一定纠正思想 因为出现了回溯 才会想到要 恢复现场

只要出现递归必定会有回溯,既然回溯中有恢复现场,那就可以这样说,只要有深度优先遍历就有恢复现场的操作。只不过在简单题恢复现场这个动作并不明显,因为参数在递归过程中就已经自动恢复现场了,但是在一些难的题里面,一旦用到全局变量,我们要手动恢复,这个恢复现场操作就会变成额外重要。

比如这道题我们用两个全局变量,path是把根到叶子节点所经历的路径记录下来,ret是把path到叶子节点后的整条路径记录下来。
在这里插入图片描述

path遇到不是叶子节点就 值 + ->,遇到叶子就把path放到ret数组中。但是此时有一个超级致命的问题,回溯的时候,path要回到上一层,你会发现回溯到上一层path不应该有 4 的,因为path往其他子树传仅需要传 1->2-> 就行了!那此时就应该 恢复现场把全局变量恢复下去之前的样子。此时还有一个问题如果把path设计成全局变量,回溯时path要不停pop,从叶子节点回溯还好说,但是从非叶子节点回溯要pop两次,挺麻烦的!

在这里插入图片描述

这道题用全局变量path记录路径比较麻烦,仅是这道题全局path不好用,但是比较麻烦的题全局path好用,这里只是为了说明,有恢复现场这个操作的。

这道题我们函数头这样设计 void dfs(root,path),把path当成参数传给函数,你会发现恢复现场特别容易,函数特性就已经帮我们恢复现场了。因为每次函数都会重新创建一个path,回溯到上一层用的还是上一层自己的path。就不用自己手动恢复了。

在这里插入图片描述

总结一下:全局变量 不好手动 恢复现场,那就 参数 自动 恢复现场

函数头,函数体都差不多了,接下来就是递归出口了,当root == nullptr 返回。但是这里递归还要进去才返回。此时我们可以剪枝,当非空进去,空就不要进!

在这里插入图片描述

class Solution {vector<string> ret;
public:vector<string> binaryTreePaths(TreeNode* root) {string path;dfs(root,path);return ret;}void dfs(TreeNode* root,string path){//if(root == nullptr) return;path+=to_string(root->val);if(root->left == nullptr && root->right == nullptr){ret.push_back(path);return;}path+="->";// dfs(root->left,path);// dfs(root->right,path);//回溯+剪枝 if就是剪枝if(root->left) dfs(root->left,path);//中间如果有就是回溯if(root->right) dfs(root ->right,path);}
};

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

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

相关文章

defineProps定义类型

1.props标注类型 原因&#xff1a;确保给组件传递的props是类型安全的 <script setup lang"ts"> //1.使用别名类型或者接口定义Props类型 type Props {name:stringage?:number } //2 使用defineProps注解类型 const props defineProps<Props>() <…

全年申报!2024年陕西省双软企业认定条件标准、申报好处费用

1.双软企业是什么? 答:双软认证并不是一个资质,而是"软件产品登记"和"软件企业认定"两个不同资质的统称.叫做"双软企业" 2.双软企业的优惠政策是什么? 答:(1)软件产品登记的优惠政策:软件产品增值税,从13%减按3%征收,实行即征即退; (2)软件…

2024Stable Diffusion WebUI详细使用指南

Stable Diffusion WebUI&#xff08;AUTOMATIC1111&#xff0c;简称A1111&#xff09;是一个为高级用户设计的图形用户界面&#xff08;GUI&#xff09;&#xff0c;它提供了丰富的功能和灵活性&#xff0c;以满足复杂和高级的图像生成需求。由于其强大的功能和社区的活跃参与&…

22 - 游戏玩法分析 IV(高频 SQL 50 题基础版)

22 - 游戏玩法分析 IV 考点&#xff1a; 聚合函数 # 日期相加 date_add(min(event_date),INTERVAL 1 DAY) select round(count(distinct player_id)/(select count(distinct player_id) from Activity),2) fraction fromActivity where-- 如果日期加一天的数据能在表中…

pytorch笔记:自动混合精度(AMP)

1 理论部分 1.1 FP16 VS FP32 FP32具有八个指数位和23个小数位&#xff0c;而FP16具有五个指数位和十个小数位Tensor内核支持混合精度数学&#xff0c;即输入为半精度&#xff08;FP16&#xff09;&#xff0c;输出为全精度&#xff08;FP32&#xff09; 1.1.1 使用FP16的优缺…

MySQL主从同步优化指南:架构、瓶颈与解决方案

前言 ​ 在现代数据库架构中&#xff0c;MySQL 主从同步是实现高可用性和负载均衡的关键技术。本文将深入探讨主从同步的架构、延迟原因以及优化策略&#xff0c;并提供专业的监控建议。 MySQL 主从同步架构 ​ 主从复制流程&#xff1a; 从库生成两个线程&#xff0c;一个…

20 - 每月交易 I(高频 SQL 50 题基础版)

20 - 每月交易 I -- 考点&#xff1a;日期转换格式 -- date_format(trans_date,%Y-%m)select date_format(trans_date,%Y-%m) month,country,count(*) trans_count,sum(if(stateapproved,1,0)) approved_count,sum(amount) trans_total_amount,sum(if(state"approved&qu…

【主题广泛|稳定检索】2024年食品安全与生物技术国际会议(ICFSB 2024)

2024年食品安全与生物技术国际会议&#xff08;ICFSB 2024&#xff09; 2024 International Conference on Food Safety and Biotechnology 【重要信息】 大会地点&#xff1a;贵阳 大会官网&#xff1a;http://www.icicfsb.com 投稿邮箱&#xff1a;icicfsbsub-conf.com 【注…

语言大模型qwen1.5全流程解析:微调,量化与推理

在前一篇文章中&#xff0c;主要使用llama-factory封装的推理模块对速度进行了测试&#xff0c;vllm速度快些&#xff0c;但仍没有传说中的快3-5倍&#xff0c;需要单独测试。这里使用qwen1.5-1.8B作为测试模型。 qwen1.5是qwen2的先行版&#xff0c;24年2月发布&#xff0c;与…

jenkins插件之Jdepend

JDepend插件是一个为构建生成JDepend报告的插件。 安装插件 JDepend Dashboard -->> 系统管理 -->> 插件管理 -->> Available plugins 搜索 Jdepend, 点击安装构建步骤新增执行shell #执行pdepend if docker exec phpfpm82 /tmp/composer/vendor/bin/pdepe…

ComfyUI工作流分享-黏土特效工作流

大家给的教程都是苹果端使用Remini的软件制作&#xff0c;免费白嫖7天&#xff0c;7天后就要收费&#xff0c;作为ComfyUI技术党&#xff0c;当然是选择自己实现了&#xff0c;搭建一套工作流就搞定&#xff0c;这不&#xff0c;今天就来分享一套对应的黏土效果工作流&#xff…

TSINGSEE青犀视频:城市道路积水智能监管,智慧城市的守护者

随着城市化进程的加快&#xff0c;城市道路网络日益复杂&#xff0c;尤其在夏季&#xff0c;由于暴雨频发&#xff0c;道路积水问题成为影响城市交通和市民生活的重要因素之一。传统的道路积水监测方式往往依赖于人工巡逻和简单的监控设备&#xff0c;这些方法存在效率低下、响…

CAN总线学习笔记-CAN帧结构

数据帧 数据帧&#xff1a;发送设备主动发送数据&#xff08;广播式&#xff09; 标准格式的11ID不够用了&#xff0c;由此产生了扩展格式 SOF&#xff1a;帧起始&#xff0c;表示后面一段波形为传输的数据位 ID&#xff1a;标识符&#xff0c;区分功能&#xff0c;同时决定优…

先进制造aps专题十一 国内软件/erp行业的现状及对aps行业的启示

看到一个帖子 中国软件行业几乎全军覆没 OSC开源社区 2024-06-03 15:58 广东 刚刚网上冲浪刷到的 网友锐评&#xff1a;都是客户关系型公司。 知名大 V 「Fenng」评论称&#xff1a; 这里所谓的软件行业公司如果立刻倒闭&#xff0c;才能够利好中国整个行业软件生态。有个网…

巨详细Linux安装Nacos教程

巨详细Linux安装Nacos教程 1、检查是否有残留nacos版本2、上传安装包至服务器2.1安装包获取2.2创建相关目录 3、安装Nacos4、配置Nacos4.1修改数据源4.2新建nacos数据库4.3启动nacos4.4把nacos进程交给systemctl管理4.5设置nacos开机自启动 1、检查是否有残留nacos版本 rpm -q…

Unity基础实践小项目

项目流程&#xff1a; 需求分析 开始界面 选择角色面板 排行榜面板 设置面板 游戏面板 确定退出面板 死亡面板 UML类图 准备工作 1.导入资源 2.创建需要的文件夹 3.创建好面板基类 开始场景 开始界面 1.拼面板 2.写脚本 注意事项&#xff1a;注意先设置NGUI的分辨率大小&…

问题:律师会见委托人的方式包括团体会见和( )。 #职场发展#笔记#学习方法

问题&#xff1a;律师会见委托人的方式包括团体会见和&#xff08; &#xff09;。 参考答案如图所示

【Python报错】已解决TypeError: can only concatenate str (not “int“) to str

成功解决“TypeError: can only concatenate str (not “int”) to str”错误的全面指南 一、引言 在Python编程中&#xff0c;字符串&#xff08;str&#xff09;和整数&#xff08;int&#xff09;是两种基本的数据类型。然而&#xff0c;当我们尝试将这两种类型的对象进行连…

[matlab]折线图之多条折线如何绘制实心圆作为标记点

使用MarkerFaceColor是标记点填充的颜色&#xff0c;b&#xff0c;表示blue&#xff0c;蓝色 plot(x, a, d--, MarkerFaceColor, b); % 绘制仿真结果的曲线如果一张图多条曲线那么每条曲线需要单独调用一次plot&#xff0c;每个plot间用hold on 连接 plot(x, a, d--, MarkerF…

通配符SSL证书快速申请攻略

一、什么是通配符SSL证书 通配符SSL证书又叫泛域名SSL证书&#xff0c;可以保护一个主域名及其所有二级子域名&#xff0c;并对该级子域名数量无限制&#xff0c;且添加新的该级子域名无须另外付费。 二、通配符SSL证书有哪些优势 1.节省时间和金钱&#xff1a;与购买和安装…