当前位置: 首页 > news >正文

代码随想录算法训练营|二叉树总结

二叉树的定义:

struct TreeNode
{int val;TreeNode* left;TreeNode* right;TreeNode():val(0),left(nullptr),right(nullptr){}TreeNode(int val):val(val),left(nullptr),right(nullptr){}TreeNode(int val,TreeNode* left,TreeNode* right):val(val),left(left),right(right){}
}

其实二叉树就是一种类似链表结构(故打好链表基础十分重要!)。

各种遍历方法

在这里插入图片描述

前序遍历

前序遍历的顺序是中左右,用一个图来感受这个过程,前序遍历:5412678

递归法

class Solution {
public:vector<int> result;void preorder(TreeNode* node){if(node==nullptr)return;result.push_back(node->val);preorder(node->left);preorder(node->right);}vector<int> preorderTraversal(TreeNode* root) {result.clear();preorder(root);return result;}
};

迭代法

上面我们采用递归能做出来,递归的本质就是栈,故迭代法可用栈这种数据结构!

class Solution {
public:vector<int> preorderTraversal(TreeNode* root) {vector<int> result;stack<TreeNode*> stk;//先判断是否需要push进去,首先需要push一个root进去,不然下面的while循环都进不去if(root==nullptr) return result;stk.push(root);while(!stk.empty()){TreeNode* node=stk.top();stk.pop();result.push_back(node->val);//一个注意点,应该先push右子树,因为栈的特点是先入后出if(node->right)stk.push(node->right);if(node->left)stk.push(node->left);}return result;}
};

中序遍历

递归法

中序遍历的顺序为左中右,参考上面的图,应该是1425768

class Solution {
public:vector<int> result;void inorder(TreeNode* node){if(node==nullptr)return;preorder(node->left);result.push_back(node->val);preorder(node->right);}vector<int> inorderTraversal(TreeNode* root) {result.clear();inorder(root);return result;}
};

迭代法

class Solution {
public:vector<int> inorderTraversal(TreeNode* root) {vector<int> result;stack<TreeNode*>stk;if(root==nullptr)return result;TreeNode* cur=root;while(!stk.empty()||cur!=nullptr){if(cur){stk.push(cur);cur=cur->left;}else{cur=stk.top();stk.pop();result.push_back(cur->val);cur=cur->right;}}return result;}
};

后序遍历

后序遍历:左右中,参考上面的图:1247865

递归法

class Solution {
public:vector<int> result;void postorder(TreeNode* node){if(node==nullptr)return;preorder(node->left);preorder(node->right);result.push_back(node->val);}vector<int> postorderTraversal(TreeNode* root) {result.clear();postorder(root);return result;}
};

迭代法

对比前序遍历顺序:中左右,后序遍历顺序为:左右中,如果我们将顺序变为:中右左,然后对于结果反转一下,是不是就是正确的呢?

class Solution {
public:vector<int> postorderTraversal(TreeNode* root) {vector<int> result;stack<TreeNode*> stk;if(root==nullptr)return result;stk.push(root);while(!stk.empty()){TreeNode* node=stk.top();stk.pop();result.push_back(node->val);if(node->left)stk.push(node->left);if(node->right)stk.push(node->right);}reverse(result.begin(),result.end());return result;}
};

层序遍历

其实上文的前中后序遍历,在图论中就是DFS(深度优先搜索),而对应还有一种方法,那就是宽度优先搜索(BFS),其实对于BFS而言,用处还是蛮大的,很多需要遍历整个树的问题,用BFS做起来蛮方便的!当然要想实现BFS,也要借用一种数据结构,其用于存储每一层的元素!这种数据结构就是queue

class Solution {
public:vector<vector<int>> levelOrder(TreeNode* root) {vector<vector<int>>result;queue<TreeNode*> que;if(root==nullptr)return result;que.push(root);while(!que.empty()){int size=que.size();vector<int>vec;//在遍历上一层的同时,也将下一层的节点加入queue,这个过程while(size--){TreeNode* node=que.front();que.pop();vec.push_back(node->val);if(node->left)que.push(node->left);if(node->right)que.push(node->right);}result.push_back(vec);}return result;}
};

二叉树遍历(带有回溯的)

236.二叉树的最近公共祖先

class Solution {
public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if(root==nullptr||root==p||root==q)return root;TreeNode* left=lowestCommonAncestor(root->left,p,q);TreeNode* right=lowestCommonAncestor(root->right,p,q);if(left&&right)return root;else if(left==nullptr&&right)return right;else if(left&&right==nullptr)return left;else return nullptr;}
};

做完这道题,明白了公共祖先的问题,都是自顶向上的遍历(采用后序遍历)以及搜索整个树采用:

        TreeNode* left=lowestCommonAncestor(root->left,p,q);TreeNode* right=lowestCommonAncestor(root->right,p,q);

同样的一道题:255.二叉搜索树的最近公共祖先,但是这道题还有一个特点,每次要遍历左子树还是右子树的时候可以先进行判断,相当于进行剪枝操作了!

分解问题

将一个二叉树分解为左子树和右子树的问题!
其实要求遍历整个树的问题,很多时候都是分解问题,比较左子树和右子树的问题!
222.完全二叉树的节点个数
这是一道最基本的分解问题,求整个树的个数,分解为左子树加右子树再加根节点!(当然这里还有要遍历整个树要怎么写的问题!)

class Solution {
public:int traversal(TreeNode* node){if(node==nullptr)return 0;int left=traversal(node->left);int right=traversal(node->right);//为什么这里是1+left+right呢?相当于左子树的个数加上右子树的个数再加上根节点(分解问题)return 1+left+right;}int countNodes(TreeNode* root) {return traversal(root);}
};

构造二叉树

关键点:在于不断确定中间节点,左子树以及右子树!
105.从前序与中序遍历序列构造二叉树

class Solution {
public:TreeNode* traversal(vector<int>& preorder,vector<int>& inorder){if(preorder.size()==0)return nullptr;int rootvalue=preorder[0];TreeNode* root=new TreeNode(rootvalue);int index=0;for(;index<inorder.size();index++){if(inorder[index]==rootvalue)break;}vector<int> leftinorder(inorder.begin(),inorder.begin()+index);vector<int> rightinorder(inorder.begin()+index+1,inorder.end());vector<int> leftpreorder(preorder.begin()+1,preorder.begin()+1+leftinorder.size());vector<int> rightpreorder(preorder.begin()+1+leftinorder.size(),preorder.end());root->left=traversal(leftpreorder,leftinorder);root->right=traversal(rightpreorder,rightinorder);return root;}TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {if(preorder.size()==0||inorder.size()==0) return nullptr;return traversal(preorder,inorder);}   
};

做过这道题,可以试试看
106.从中序与后序遍历序列构造二叉树

二叉搜索树

1.有序的问题!(联系中序遍历),求二叉搜索树中第k个最小值!一般做法:采用中序遍历,将二叉树变为有序数组,一定要采用中序遍历!
230.二叉搜索树中第K小的元素

class Solution {
public:vector<int> result;void inorder(TreeNode* root){if(root==nullptr)return;inorder(root->left);result.push_back(root->val);inorder(root->right);}int kthSmallest(TreeNode* root, int k) {inorder(root);return result[k-1];}
};

98.验证二叉搜索树
这两道题都是将二叉搜索树的问题转换成数组问题来解决的!故对于二叉搜索树的很多问题一定要学会联系中序遍历!

路径问题

插入节点

701.二叉搜索树中的插入操作

class Solution {
public:TreeNode* insertIntoBST(TreeNode* root, int val) {if(root==nullptr){TreeNode* node=new TreeNode(val);return node;}if(root->val<val){root->right=insertIntoBST(root->right,val);}if(root->val>val){root->left=insertIntoBST(root->left,val);}return root;}
};

删除节点

450.删除二叉搜索树的节点

class Solution {
public:TreeNode* deleteNode(TreeNode* root, int key) {if(root==nullptr)return nullptr;if(root->val==key){if(root->left==nullptr)return root->right;else if(root->right==nullptr)return root->left;else if(root->left!=nullptr && root->right!=nullptr){TreeNode* cur=root->right;while(cur->left!=nullptr){cur=cur->left;}cur->left=root->left;TreeNode* temp=root;root=root->right;delete temp;return root;}}if(root->val<key)root->right=deleteNode(root->right,key);if(root->val>key)root->left=deleteNode(root->left,key);return root;}
};

相关文章:

代码随想录算法训练营|二叉树总结

二叉树的定义&#xff1a; struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode():val(0),left(nullptr),right(nullptr){}TreeNode(int val):val(val),left(nullptr),right(nullptr){}TreeNode(int val,TreeNode* left,TreeNode* right):val(val),left(left),…...

rtt的io设备框架面向对象学习-uart设备

目录 1.uart设备基类2.uart设备基类的子类3.初始化/构造流程3.1设备驱动层3.2 设备驱动框架层3.3 设备io管理层 4.总结5.使用 1.uart设备基类 此层处于设备驱动框架层。也是抽象类。 在/ components / drivers / include / drivers 下的serial.h定义了如下uart设备基类 struc…...

PyCharm - Script parameters (脚本参数)

PyCharm - Script parameters [脚本参数] References Run -> Edit Configurations… -> Run/Debug Configurations -> Configuration -> Script parameters 命令行&#xff1a; python display_yolo_log.py ./person_training_log/person_train_log_DIMM40_stdout…...

Security6.2 中的SpEL 表达式应用(权限注解使用)

最近学习若依框架&#xff0c;里面的权限注解涉及到了SpEL表达式 PreAuthorize("ss.hasPermi(system:user:list)")&#xff0c;若依项目中用的是自己写的方法进行权限处理&#xff0c; 也可以只用security 来实现权限逻辑代码&#xff0c;下面写如何用security 实现。…...

软考笔记--信息系统开发方法(下)

信息系统是一个极其复杂的人机交互系统&#xff0c;它不仅包含计算机技术&#xff0c;通信技术和网络规划以及其他的工程技术&#xff0c;而且&#xff0c;它还是一个复杂的管理系统&#xff0c;需要管理理论和方法的支持&#xff0c;因此&#xff0c;与其他工程项目相比&#…...

从 AGP 4.1.2 到 7.5.1——XmlParser、GPathResult、QName 过时

新年首发&#xff0c; 去年的问题&#xff0c;今年解决~ 问题 & 排查 1: Task failed with an exception. ----------- * What went wrong: Execution failed for task :app:processCommonReleaseManifest. > org.xml.sax.SAXParseException; lineNumber: 1; columnNu…...

spring boot 使用AOP实现是否已登录检测

前后端分离的开发中&#xff0c;用户http请求应用服务的接口时, 如果要求检测该用户是否已登录。可以实现的方法有多种&#xff0c; 本示例是通过aop 的方式实现&#xff0c;简单有效。 约定&#xff1a;前端http的post 请求 export async function request(url,data) {const …...

为什么从没有负值的数据中绘制的小提琴图(Violin Plot)会出现负值部分?

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 小提琴图&#xff08;Violin Plot&#xff09; 是一种用于展示和比较数据分布的可视化工具。它结合了箱形图&#xff08;Box Plot&#xff09;和密度图&#xff08;Kernel Density Plot&#xff09;的特…...

有哪几种行为会导致服务器被入侵

导致服务器被入侵的行为有很多种&#xff0c;以下是一些常见的行为&#xff1a; 系统漏洞&#xff1a;服务器操作系统或软件存在漏洞&#xff0c;攻击者可以通过利用这些漏洞获取系统权限&#xff0c;从而入侵服务器。 弱口令&#xff1a;服务器的账号密码过于简单或者未及时更…...

Redis RabbitMQ

Redis&#xff1a;轻量级&#xff0c;NoSQL数据库 redis是一个key-value存储系统。和Memcached类似&#xff0c;它支持存储的value类型相对更多&#xff0c;包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash&#xff08;哈希类型&#xff09;。这…...

http 和 https 的区别?

目录 1.http 和 https 的基本概念 2.http 和 https 的区别 3.https 协议的工作原理 4.https 协议的优点 5.https 协议的缺点 1.http 和 https 的基本概念 http: 超文本传输协议&#xff0c;是互联网上应用最为广泛的一种网络协议&#xff0c;是一个客户端和服务器端请求和…...

C++中线程的创建

线程创建 引言为什么要使用线程线程的创建使用函数指针示例运行结果使用类对象示例运行结果使用lambda表达式示例运行结果使用带参数的函数作为线程处理函数示例运行结果使用类成员函数示例运行结果引言 在学习C++的过程中,线程的使用作为一个非常重要的部分,也是在复杂项目…...

基于JavaWeb开发的家政服务平台计算机毕业设计[附源码]

基于JavaWeb开发的家政服务平台计算机毕业设计[附源码] &#x1f345; 作者主页 央顺技术团队 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 文末获取源码联系方式 &#x1f4dd; &#x1f345; 查看下方微信号获取联系方式 承接各种定制系统…...

性能调优:容易忽视的JavaScript标签属性及其性能影响

在性能优化中&#xff0c;我们都知道&#xff0c;async属性可以让script标签变得不阻塞HTML解析&#xff0c;defer属性也有类似的功能&#xff0c;但实际defer是会阻塞script解析的&#xff08;用defer的话&#xff0c;多个script会按顺序执行&#xff0c;而async执行是无序的&…...

【机器学习笔记】7 KNN算法

距离度量 欧氏距离(Euclidean distance) 欧几里得度量&#xff08;Euclidean Metric&#xff09;&#xff08;也称欧氏距离&#xff09;是一个通常采用的距离定义&#xff0c;指在&#x1d45a;维空间中两个点之间的真实距离&#xff0c;或者向量的自然长度&#xff08;即该点…...

mysql 2-20

TEXT类型 枚举类型 SET类型 二进制字符串类型 BLOB类型 注意事项 JSON类型 提取数据 空间类型 选择建议 约束...

Unity3D Shader 素描风格渲染管线实现详解

前言 在游戏开发中&#xff0c;渲染效果是非常重要的一部分&#xff0c;它可以直接影响游戏的视觉效果和玩家的体验。而素描风格的渲染效果是一种非常独特和有趣的风格&#xff0c;可以为游戏增添一种艺术氛围。在Unity3D中&#xff0c;可以通过编写Shader来实现素描风格的渲染…...

WordPress站点如何实现发布文章即主动推送到百度快速收录和普通收录?

我们在WordPress后台成功发布文章之后&#xff0c;如果靠搜索引擎来抓取的话&#xff0c;可能会比较慢&#xff0c;所以十分有必要将我们成功发布的文章马上提交到百度、必应等搜索引擎中。下面boke112百科就跟大家说一说WordPress站点如何实现发布文章即主动推送到百度快速收录…...

C++11---(3)

目录 一、可变参数模板 1.1、可变参数模板的概念 1.2、可变参数模板的定义方式 1.3、如何获取可变参数 二、lambda表达式 2.1、Lamabda表达式定义 2.2、为什么有Lambda 2.3、Lambda表达式的用法 2.4、函数对象与lambda表达式 三、包装器 3.1、function 3.2、bind …...

【常识】大数据设计基础知识

底层存储&#xff1a;hadoop&#xff08;hdfsmapreduce&#xff09; Hadoop已经有十几年的历史&#xff0c;它是大数据领域的存储基石&#xff0c;HDFS目前仍然没有成熟替代品;MapR 文件系统在业内已经具有一定知名度了&#xff0c;不仅 MapR 宣布它自己的文件系统比 HDFS 快2-…...

RestClient

什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端&#xff0c;它允许HTTP与Elasticsearch 集群通信&#xff0c;而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级&#xff…...

【kafka】Golang实现分布式Masscan任务调度系统

要求&#xff1a; 输出两个程序&#xff0c;一个命令行程序&#xff08;命令行参数用flag&#xff09;和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽&#xff0c;然后将消息推送到kafka里面。 服务端程序&#xff1a; 从kafka消费者接收…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

剑指offer20_链表中环的入口节点

链表中环的入口节点 给定一个链表&#xff0c;若其中包含环&#xff0c;则输出环的入口节点。 若其中不包含环&#xff0c;则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

深度学习习题2

1.如果增加神经网络的宽度&#xff0c;精确度会增加到一个特定阈值后&#xff0c;便开始降低。造成这一现象的可能原因是什么&#xff1f; A、即使增加卷积核的数量&#xff0c;只有少部分的核会被用作预测 B、当卷积核数量增加时&#xff0c;神经网络的预测能力会降低 C、当卷…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...