[算法2] 第二集 二叉树中的深度搜索

深度优先遍历(DFS,全称为 Depth First Traversal),是我们树或者图这样的数据结构中常⽤的
⼀种遍历算法。这个算法会尽可能深的搜索树或者图的分支,直到⼀条路径上的所有节点都被遍历
完毕,然后再回溯到上⼀层,继续找⼀条路遍历。
在⼆叉树中,常见的深度优先遍历为:前序遍历、中序遍历以及后序遍历。
因为树的定义本⾝就是递归定义,因此采⽤递归的方法去实现树的三种遍历不仅容易理解⽽且代码很简洁。并且前中后序三种遍历的唯⼀区别就是访问根节点的时机不同,在做题的时候,选择⼀个适当的遍历顺序,对于算法的理解是非常有帮助的。

一、计算布尔二叉树的值

1.题目描述

2.算法思路

书面解释就是:

1. 对于规模为 n 的问题,需要求得当前节点值。
2. 节点值不为 0 或 1 时,规模为 n 的问题可以被拆分为规模为 n-1 的子问题:
a. 所有子节点的值;
b. 通过子节点的值运算出当前节点值。
3. 当问题的规模变为 n=1 时,即叶⼦节点的值为 0 或 1,我们可以直接获取当前节点值为 0 或 1。
画图来理解一下:
我们如果想知道根节点true or false,我们需要知道其子节点,true or false,进而层层递归

3.代码实现

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;}
};

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

1.题目描述

2.算法思路

通过前序遍历,往左右子树传递信息,并且在回溯时得到左右子树的返回值。让递归函数完成两件事:
1. 将父节点的数字与当前节点的信息整合到⼀起,计算出当前节点的数字,然后传递到下⼀层进行递归;
2. 当遇到叶子节点的时候,就不再向下传递信息,将整合的结果向上⼀直回溯到根节点。
在递归结束时,根节点需要返回的值也就被更新为了整棵树的数字和。
递归函数设计:int dfs(TreeNode* root, int num)
1. 返回值:当前子树计算的结果(数字和);
2. 参数 num:递归过程中往下传递的信息(父节点的数字);
3. 函数作用:整合父节点的信息与当前节点的信息计算当前节点数字,并向下传递,再回溯时返回当前子树(当前节点作为子树根节点)数字和。
我们画图来理解一下,举个例子:
我们有如下二叉树
首先,我们 合父节点的信息与当前节点的信息计算当前节点数字,并向下传递:
溯时返回当前子树(当前节点作为子树根节点)数字和:
最后返回计算的和就行了
递归函数流程:
1. 当遇到空节点的时候,说明这条路从根节点开始没有分⽀,返回 0;
2. 结合⽗节点传下的信息以及当前节点的 val,计算出当前节点数字 sum;
3. 如果当前结点是叶子节点,直接返回整合后的结果 sum;
4. 如果当前结点不是叶父节点,将 sum 传到左右子树中去,得到左右子树中节点路径的数字和,然 后相加后返回结果。

3.代码实现

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

三、二叉树剪枝

1.题目描述

2.算法思路

如果我们选择从上往下删除,我们需要收集左右⼦树的信息,这可能导致代码编写相对困难。然而, 通过观察我们可以发现,如果我们先删除最底部的叶子节点,然后再处理删除后的节点,最终的结果并不会受到影响。 因此,我们可以采⽤后序遍历的方式来解决这个问题。在后序遍历中,我们先处理左子树,然后处理 右子树,最后再处理当前节点。在处理当前节点时,我们可以判断其是否为叶子节点且其值是否为 0,
如果满足条件,我们可以删除当前节点。
• 需要注意的是,在删除叶子节点时,其父节点很可能会成为新的叶子节点。因此,在处理完子节点后,我们仍然需要处理当前节点。这也是为什么选择后序遍历的原因(后序遍历⾸先遍历到的一定是叶子节点)。
• 通过使用后序遍历,我们可以逐步删除叶子节点,并且保证删除后的节点仍然满足删除操作的要
求。这样,我们可以较为方便地实现删除操作,而不会影响最终的结果。
• 若在处 理结束后所有叶子节点的值均为 1,则所有子树均包含 1,此时可以返回。
算法流程:
递归函数设计:void dfs(TreeNode*& root)
1. 返回值:无;
2. 参数 :当前需要处理的节点;
3. 函数作用:判断当前节点是否需要删除,若需要删除,则删除当前节点。
后序遍历的主要流程:
1. 递归出口:当传入节点为空时,不做任何处理;
2. 递归处理左子树;
3. 递归处理右子树;
4. 处理当前节点:判断该节点是否为叶⼦节点(即左右⼦节点均被删除,当前节点成为叶子节点),
并且节点的值为 0:
a. 如果是,就删除掉;
b. 如果不是,就不做任何处理。

3.代码实现:

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){delete root; // 防⽌内泄漏root = nullptr;}return root;}
};

四、验证二叉搜索树

1.题目描述

2.算法思路

 如果一棵树是二叉搜索树,那么它的中序遍历的结果一定是⼀个严格递增的序列。 因此,我们可以初始化⼀个无穷小的全区变量,用来记录中序遍历过程中的前驱结点。那么就可以在中序遍历的过程中,先判断是否和前驱结点构成递增序列,然后修改前驱结点为当前结点,传入下一层的递归中。
算法流程:
  1.  初始化⼀个全局的变量 prev,⽤来记录中序遍历过程中的前驱结点的 val;
  2.  中序遍历的递归函数中:
    a. 设置递归出⼝:root == nullptr 的时候,返回 true;
    b. 先递归判断左⼦树是否是⼆叉搜索树,⽤ retleft 标记;
    c. 然后判断当前结点是否满⾜⼆叉搜索树的性质,用 retcur 标记:
    ▪ 如果当前结点的 val ⼤于 prev,说明满足条件,retcur 改为 true;
    ▪ 如果当前结点的 val ⼩于等于 prev,说明不满⾜条件,retcur 改为 false;
    d. 最后递归判断右⼦树是否是⼆叉搜索树,⽤ retright 标记;
  3. 只有当 retleft、 retcur 和 retright 都是 true 的时候,才返回 true。

3.代码实现

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)cur = true;// 剪枝if(cur == false) return false;prev = root->val;bool right = isValidBST(root->right);return left && right && cur;}
};​

感谢大家的观看,如有错误欢迎指正!

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

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

相关文章

Steinberg SpectraLayers Pro for Mac:专业音频频谱编辑的巅峰之作

Steinberg SpectraLayers Pro for Mac是一款专为音频专业人士设计的专业音频频谱编辑器,它以其强大的频谱编辑功能和直观的操作界面,在音频处理领域树立了新的标杆。该软件不仅为音频编辑工作带来了前所未有的精确度和灵活性,还极大地提升了音…

WPF 数据模板DataTemplate、控件模板ControlTemplate、Style、ItemsPreseter

一言蔽之,Template就是“外衣”—— ControlTemplate是控件的外衣, DataTemplate是数据的外衣。 DataTemplate 它定义了一个数据对象的可视化结构 DataTemplate常用的地方有3处,分别是: ContentControl的ContentTemplate属性&…

CODEXGRAPH:突破代码与AI的壁垒,开启智能编程新时代

CODEXGRAPH:突破代码与AI的壁垒,开启智能编程新时代 CODEXGRAPH论文阅读1. 概述2. 相关研究代码库级别的任务检索增强代码生成(RACG) 3. CODEXGRAPH系统设计代码图数据库的构建与图数据库的交互 4. 实验设计与结果CrossCodeEvalSW…

数据结构---单链表实现

单链表是什么 我的理解是“特殊的数组”,通过访问地址来连接起来 1怎么创建链表 ----通过结构体(成员有存入数据的data和指向下一个节点的地址的指针(结构体指针)next 初始架构---DataType 对应存入数据类型,此处的N…

数字引领风尚·智能改变生活“青岛电博会”路演活动(济南站)

2024CICE中国国际消费电子博览会路演活动(济南站)成功举行 数字引领风尚,智能改变生活。 8月7日,50余家行业协会、企业嘉宾、展商代表等云集2024中国国际消费电子博览会路演活动(济南站)现场,共…

瑞萨电子并购Altium 引领行业创新与发展

公开资料显示,2023 年 6 月,瑞萨电子曾宣布在 Altium 的 Altium 365 云平台上实现了所有 PCB 设计的标准化开发。瑞萨电子一直与 Altium 合作,将其所有产品的 ECAD 库发布到 Altium Public Vault。借助 Altium365 上的制造商零件搜索等功能&a…

Wireshark分析工具

简单用例 首先打开软件,左上角点文件,选中要分析的文件列表。 导入用tcpdump抓的包后进行分析,这里要输入过滤条件,对网络包进行一定的过滤处理。(这里172网段是阿里云的地址,用自己写的python2脚本对阿里云进行压测。) 这里输入过滤条件 tcp.port == 80 ,语法含义是…

Java虚拟机:类的加载机制

大家好,我是栗筝i,这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 034 篇文章,在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验,并希望进…

【ARM CoreLink 系列 5.1 -- CI-700 各种 Node 组件详细介绍】

请阅读【ARM CoreLink 文章专栏导读】 文章目录 CI-700 组件(Components)RN-I( I/O-coherent Request Node) 和 RN-D(I/O coherent Request Node with DVM)HN-F(Fully coherent Home Node)IO coherent Home Node (HN-I)IO coherent Home Node with Debug Trace Controller (H…

43.【C语言】指针(重难点)(F)

目录 15.二级指针 *定义 *演示 16.三级以及多级指针 *三级指针的定义 *多级指针的定义 17.指针数组 *定义 *代码 18.指针数组模拟二维数组 往期推荐 15.二级指针 *定义 之前讲的指针全是一级指针 int a 1; int *pa &a;//一级指针 如果写成 int a 1; int *pa &a…

机器学习——线性回归(sklearn)

目录 一、认识线性回归 1. 介绍 2. 多元线性回归的基本原理(LinearRegression) 二、多重共线性 1. 介绍 2. 多重共线性详细解释 三、岭回归(解决多重共线性问题) 1. 模型推导 2. 选取最佳的正则化参数取值 四、Lasso&am…

景联文科技:破解数据标注行业痛点,引领高质量AI数据服务

数据标注行业是人工智能和机器学习领域中一个非常重要的组成部分。随着AI技术的发展,对高质量标注数据的需求也在不断增长。 数据标注市场的痛点 1. 团队管理 在众包和转包模式下,管理大量的标注人员是一项挑战。 需要确保标注人员的专业性、稳定性和…

Pod的调度机制

文章目录 一、Pod调度概述二、Pod调度策略实现方式三、kube-scheduler调度1、kube-scheduler调度的流程2、过滤阶段3、打分阶段4、kube-scheduler 调度示例4.1、创建 Deployment 资源清单4.2、应用Deployment4.3、查看被kube-scheduler自动调度的Pod 四、nodeName调度1、创建Po…

Linux驱动入门实验班——LED驱动(附百问网视频链接)

目录 一、确定引脚编号 二、编写思路 2.1驱动层 2.2应用层 三、源码 四、实现 课程链接 一、确定引脚编号 首先,可以在开发板上执行如下命令查看已经在使用的GPIO状态: cat /sys/kernel/debug/gpio 可以看到每个gpio都有对应的编号,…

火语言RPA--火语言界面应用多窗体详解

多窗体 界面应用建立时默认加载一个窗体,若是程序运行时需要多个窗体配合,在通常情况下,您可将多窗体绑定在UI控件事件中,由界面交互来打开多窗体。 本章将介绍下如何建立多窗体以及在应用中如何运用多窗体完成多种场景的设置。 …

源代码防泄密怎么做?最好用的12款源代码加密软件推荐

源代码是企业的核心资产之一,其安全性直接关系到产品的竞争力和市场地位。防止源代码泄密是企业信息安全中的重中之重,本文将介绍几种有效的源代码防泄密方法,并推荐12款优秀的源代码加密软件。 1. 代码审查与权限管理 通过严格的代码审查流…

【MySQL】用户管理——用户、用户信息、创建用户、删除用户、修改用户密码、数据库的权限、给用户权限、回收权限

文章目录 MySQL1. 用户管理1.1 用户1.1.1 用户信息1.1.2 创建用户1.1.3 删除用户1.1.4 修改用户密码 1.2 数据库的权限1.2.1 给用户权限1.2.2 回收权限 MySQL 1. 用户管理 为什么MySQL要引入用户管理? 如果我们只能使用root用户,这样存在安全隐患。因为r…

[C++][opencv]基于opencv实现photoshop算法可选颜色调整

【测试环境】 vs2019 opencv4.8.0 【效果演示】 【核心实现代码】 SelectiveColor.hpp #ifndef OPENCV2_PS_SELECTIVECOLOR_HPP_ #define OPENCV2_PS_SELECTIVECOLOR_HPP_#include "opencv2/core.hpp" #include "opencv2/imgproc.hpp" #include "…

Mariadb数据库本机无密码登录的问题解决

Mariadb数据库本机无密码登录的问题解决 安装了mariadb后,发现Mariadb本机无密码才能登录 百度了很多文章,发现很多人是因为root的plugin设置的值不正确导致的,unix_socket可以不需要密码,mysql_native_password 是正常的。 解…

NLP_情感分类_预训练加微调方案

文章目录 项目背景代码导包一些模型以及训练的参数设置定义dataset定义模型读取数据声明训练及测试数据集将定义模型实例化打印模型结构模型训练测试集效果 同类型项目 项目背景 项目的目的,是为了对情感评论数据集进行预测打标。在训练之前,需要对数据…