leetcode刷题(6):二叉树的使用

文章目录

    • 104. 二叉树的最大深度
      • 解题思路
      • c++ 实现
    • 94. 二叉树的中序遍历
      • 解题思路
      • c++ 实现
    • 101. 对称二叉树
      • 解题思路
      • c++ 实现
    • 96. 不同的二叉搜索树
      • 解题思路
      • c++ 实现
    • 102. 二叉树的层序遍历
      • 解题思路
      • c++ 实现

104. 二叉树的最大深度

题目: 给定一个二叉树 root ,返回其最大深度。

二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。

示例:
在这里插入图片描述

解题思路

  • 没有左右子节点的节点,称为叶子节点
node->left ==nullptr && node->right ==nullptr`
  • 叶子节点所在的层数,就是从跟节点到叶子节点的距离
  • 统计遍历所有节点,找到叶子节点
    • 如果当前节点不是叶子节点,则判断该节点左节点或右节点是否叶子节点
    • 记录每个叶子节点,所在层数,找到最远距离的叶子节点

c++ 实现

class Solution {
public:int ans =0;void dfs(TreeNode* root, int level){if (root ==nullptr) return;if(root->left==nullptr && root->right==nullptr){ans = max(ans,level);}dfs(root->left,level+1);dfs(root->right,level+1);}int maxDepth(TreeNode* root) {dfs(root,1);return ans;}
};
  • 定义dfs函数,传入节点以及所在的层level; 因为当前节点所在的层等于跟节点到该节点的距离,可以用level来表示距离
  • 首先从跟节点root开始遍历,对应的level为1;
  • 如果到达叶子节点,则更新最远距离ans
  • 然后接着从root->left开始,以及root->right开始寻找叶子节点,当前节点所在层为level+1
  • 最终遍历完所有节点,找到最远距离ans

94. 二叉树的中序遍历

题目: 给定一个二叉树的根节点 root ,返回 它的 中序 遍历
示例:
在这里插入图片描述

解题思路

  • 中序遍历: left -> root ->right(左中右)
  • 递归遍历,首先考虑dfs

c++ 实现

class Solution {
public:vector<int> ans;void dfs(TreeNode* root){if (root==nullptr) return;dfs(root->left);ans.push_back(root->val);dfs(root->right);}vector<int> inorderTraversal(TreeNode* root) {dfs(root);return ans;}
};
  • 完整c++ 调试代码
#include <iostream>
#include <vector>
using namespace std;struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x):val(x),left(nullptr),right(nullptr) {};
};class Solution {
public:vector<int> inorderTraversal(TreeNode* root){vector<int> result;inorder(root,result);return result;}
private:void inorder(TreeNode* root, vector<int>& result){if (root == nullptr) return;inorder(root->left,result);result.push_back(root->val);inorder(root->right,result);}
};int main()
{// 示例二叉树: 1 /   \ 2     3// 创建二叉树TreeNode* root = new TreeNode(1);root->left = new TreeNode(2);root->right = new TreeNode(3);// 使用中序遍历函数Solution solution;vector<int> inorderTraversalResult = solution.inorderTraversal(root);// 打印结果for (int val:inorderTraversalResult){cout << val << " ";}// 清理内存delete root->left;delete root->right;delete root;return 0;
}

101. 对称二叉树

题目: 给你一个二叉树的根节点 root , 检查它是否轴对称。
示例:
在这里插入图片描述

解题思路


观察对称二叉树,查找满足对称的条件,可以发现

  • 对称树,它的子节左右对称,因此子节点需相同(如图红色的2和2)
  • 同时,子节点的孙子节点,左右两侧也要满足对称,即 left_tree->left = right_tree->right; left_tree->right = right_tree->left;
  • 找到规律后,递归遍历二叉树,判断二叉树是否对称。

参考:https://www.cnblogs.com/itdef/p/14400148.html

c++ 实现

class Solution {
public:bool dfs(TreeNode* l,TreeNode* r){//遍历到最后,都没有找到不相等的节点,那么就是对称的if(l==nullptr && r==nullptr) return true;if(l==nullptr && r !=nullptr) return false;if(l!=nullptr && r==nullptr) return false;if(l->val !=r->val) return false;// if(l->val ==r->val) return true; // 如果加了这一句,则这棵树遍历到存在左右节点相同,就不继续向下遍历了,因此不要加return dfs(l->left,r->right) && dfs(l->right,r->left); }bool isSymmetric(TreeNode* root) {return dfs(root->left,root->right);}
};
  • 如果遍历过程中,左右存在任意不相等的,则直接判断不是对称树
  • 如果遍历到最后,都没有发现不相等。因为已经到树的最后,此时 l->leftr->right都为空,而且l->right和l->left也都是空, 根据if(l==nullptr && r==nullptr) return true;此时dfs(l->left,r->right) && dfs(l->right,r->left)返回true
  • 注意不要加:if(l->val ==r->val) return true, 不然遍历不到树的最后,只要在中间节点存在满足这一要求的,就停止判断了,无法对整棵树进行判断。

96. 不同的二叉搜索树

题目: 给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?``返回满足题意的二叉搜索树的种数
示例:
在这里插入图片描述

解题思路

二叉搜索树, 也称二叉排序树二叉查找树。具有下列性质的二叉树:

  • 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值
  • 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值
  • 它的左、右子树也分别为二叉排序树。
  • 二叉搜索树作为一种经典的数据结构,它既有链表的快速插入与删除操作的特点,又有数组快速查找的优势
  • 使用动态规划dp的方法求解, 设dp[n]记录n个连续节点(从 1 到 n 互不相同)组成的二叉搜索树的种类。
  • 二叉搜索树,左子树上的所有节点均小于它的跟节点,右子树上的所有节点均大于它的跟节点
  • 可知dp[1]1, 因为只有一个节点,排列的可能就只有一种;另外dp[0]也为1,因为也只有一种排列可能。dp[2] 可组成两种不同的搜索二叉树,因此dp[2]=2
    在这里插入图片描述
  • 对于3个节点,列出了所有的不同的搜索二叉树, 总共有5种
    • 如果1作为根节点,由于找不到比跟节点小的数作为左子树,因为左子树为空(dp[0]), 此时2,3两个节点在右子树上存在2种搜索二叉树的可能,也就是dp[2]:如果2在右子树上,那么3由于比2大,那么3只能是它的右子节点。如果3在右子树上,由于2比3小,2只能是它的左子节点); 此时种类数为: dp[0] * dp[2] = 2
      在这里插入图片描述
    • 如果2作为跟节点, 因为1比跟节点2小1只能是它的左节点,由于3比2大3只能是根节点2的右节点, 因此只有1种可能:因此种类计算为 dp[1]*dp[1] =1
    • 如果3作为跟节点,由于没有比它大的数,所以右子树为空,也就是dp[0],剩下的两个数字都在左子树上,对应为dp[2]: 如果1作为跟节点3的左节点,那么剩下的2只能是1的右节点(2比1大);如果2作为跟节点3的左子节点,那么剩下的1只能是2的左子节点(1比2小)。因此种类计算为 dp[2]*dp[0] =2
    • 所以对于3个节点来说,所有的二叉树为: dp[0] * dp[2] + dp[1]*dp[1] + dp[2]*dp[0] =5

因此得出如下规律:

  • (1)遍历每个数,作为根节点
  • (2) 计算该跟节点下,所有搜索二叉树的种类左子树(种类)* 右字数(种类)
  • (3) 最后将计算结果求和

c++ 实现

class Solution {
public:int numTrees(int n) {int dp[20]; memset(dp,0x0,sizeof(dp));dp[0] =1;dp[1] =1;// 遍历p[i]for(int i=2;i<=n;i++){   // i个节点,元素值 <=i; 遍历以每个节点作为跟节点for (int j=1;j<=i;j++){dp[i] += dp[j-1] * dp[i-j];}}return dp[n];}
};
  • 首先初始化dp[20] , 并通过memset 置为0 ,因为n<=19, 初始化的大小足够了。
  • 其中:dp[0] 和dp[1] 都为1
  • 通过遍历 for(int i=2;i<=n;i++)来计算p[i]的值
  • 对于i个节点,元素值 <=i; 遍历以每个节点作为跟节点, 计算此时搜索二叉树的种类
dp[j-1] * dp[i-j]
  • 因为左节点元素小于根节点,所以为dp[j-1], 根据解题思路的总结,右节点对应为dp[i-j] , 因为j-1+i-j =i-1;

102. 二叉树的层序遍历

题目:给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

示例:
在这里插入图片描述

解题思路

BFS 广度优先搜索算法的介绍,看出博文: BFS和DFS优先搜索算法

  • BFS遍历二叉树 ,添加了遍历的树的层级level
  • 根据层级决定新开vector或者直接push

在这里插入图片描述

  • 先将跟节点root层级0,加入到队列queue中,然后遍历队列
  • 首先弹出根节点,并拿到节点值存储到ans中
  • 根节点下一层子节点加入队列
  • 然后继续弹出队列中的节点,如果节点层级大于curr节点,增需要重新开一个vector,存储该节点的值,如果和当前层级是一样的,则直接push_back到vector中。
  • 然后pop该节点,并将该节点的下一层子节点添加队
  • 继续上述步骤,直到全部遍历完。。。。

c++ 实现

class Solution {
public:vector<vector<int>> ans;int curr =0;       // current levelvector<int> v;     // 单个level 保存的结果void bfs(TreeNode* root){if(root==nullptr) return;//创建用来存储节点和level的queuequeue<pair<TreeNode*,int>> q;// 放入第一个节点,同时记录节点的层级q.push({root,0});while(!q.empty()){// 循环弹出需要处理的节点TreeNode* p=q.front().first;int level = q.front().second;// 记得从队列中pop掉q.pop();// 如果处理的节点层级比当前vector层级更大// 那么说明上一层的节点数据已经处理完毕,需要重新开一个vector来记录新的层级节点if(level>curr){// 更新curr 层级curr = level;// 将已经处理完毕的层级数据vector, 添加到ans结果中ans.push_back(v);// 得到一个空的vector, 用于记录新的层级数据v.clear();v.push_back(p->val);}else{//如果处理节点的层级和当前curr层级一样,直接push_back即可v.push_back(p->val);}// 将当前处理的节点的子节点,放入队列中,注意要加上子节点所在的层级if (p->left !=nullptr) q.push({p->left,level+1});if (p->right !=nullptr) q.push({p->right,level+1});}// 记得将最后一次的结果v,加入ans中ans.push_back(v);return;}vector<vector<int>> levelOrder(TreeNode* root) {bfs(root);return ans;}
};
  • 首先创建一个队列queue来节点及所在level, 并插入根节点
//创建用来存储节点和level的queue
queue<pair<TreeNode*,int>> q;
// 放入第一个节点,同时记录节点的层级
q.push({root,0});
  • 遍历队列,循环弹出需要处理的节点
// 循环弹出需要处理的节点TreeNode* p=q.front().first;int level = q.front().second;// 记得从队列中pop掉q.pop();
  • 如果处理的节点层级比当前vector层级更大,那么说明上一层的节点数据已经处理完毕,需要重新开一个vector记录新的层级节点
if(level>curr){// 更新curr 层级curr = level;// 将已经处理完毕的层级数据vector, 添加到ans结果中ans.push_back(v);// 得到一个空的vector, 用于记录新的层级数据v.clear();v.push_back(p->val);}
  • 如果处理节点的层级和当前curr层级一样,直接push_back即可
 else{//如果处理节点的层级和当前curr层级一样,直接push_back即可v.push_back(p->val);}
  • 然后将pop掉的当前节点p的(下一层级)子节点加入队列queue, 同时它的level+1
if (p->left !=nullptr) q.push({p->left,level+1});
if (p->right !=nullptr) q.push({p->right,level+1});
  • 队列遍历完,记得将最后一次结果v加入到ans中
        // 记得将最后一次的结果,加入ans中ans.push_back(v);

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

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

相关文章

ALV 图标显示

前言 在ABAP ALV中&#xff0c;使用fieldcat来定义列表中每个字段的显示属性&#xff0c;包括图标&#xff08;Icon&#xff09;的显示。图标可以在ALV列表中为特定列的行或标题添加图形元素&#xff0c;以增强视觉提示或传达附加信息。 ICON查询 图标的名称用事务码”ICON“进…

智能BI(后端)-- 系统异步化

文章目录 系统问题分析什么是异步化&#xff1f;业务流程分析标准异步化的业务流程系统业务流程 线程池为什么需要线程池&#xff1f;线程池两种实现方式线程池的参数线程池的开发 项目异步化改造 系统问题分析 问题场景&#xff1a;调用的服务能力有限&#xff0c;或者接口的…

【文档理解】TextMonkey:一种OCR-Free的用于文档理解的多模态大模型

背景 传统的信息提取&#xff0c;通常是从文本中提取信息&#xff0c;相关技术也比较成熟。然而对于复杂领域&#xff0c;例如图片&#xff0c;文档等形式的数据&#xff0c;想要提取出高质量的、可信的数据难度就比较大了&#xff0c;这种任务也常称为&#xff1a;视觉文档理…

CTF网络安全大赛web题目:just_sqli

这道题目是bugku的web题目 题目的 描  述: KosenCTF{} 原文链接&#xff1a; CTF网络安全大赛web题目&#xff1a;just_sqli - 红客网-网络安全与渗透技术 题目Web源代码&#xff1a; <?php$user NULL; $is_admin 0;if (isset($_GET["source"])) {highlig…

齐护K210系列教程(二十七)_语音识别

语音识别 1.烧录固件和模型2.语音识别程序2.1训练并识别2.2使用本地文件语音识别 3.课程资源联系我们 1.烧录固件和模型 注&#xff1a;本应用只适用于有麦克风功能的型号&#xff1a;AIstart_pro、AIstart_掌机、AIstart_Mini, 其它型号不支持&#xff01; 机器码生成以及模…

linux中远程服务器上传输文件的10个sftp命令示例

目录 1. 如何连接到 SFTP 2. 帮助 3.检查当前工作目录 4. 使用 sftp 列出文件 远程 本地 5. 使用 sftp 上传文件 6. 使用 sftp 上传多个文件 7. 使用 sftp 下载文件 8. 在 sftp 中切换目录 远程 本地 9. 使用 sftp 创建目录 10. 使用 sftp 删除目录 11. 退出 sf…

(001)apidoc 的安装

安装 1.确定 node 和 npm 的匹配版本 node -vv10.14.1# 切换node 版本 nvm list nvm use 20.12.22.安装 apidoc。 npm install -g apidoc3.生成文档&#xff1a; apidoc -i ../ -o document/ -f ".java$"-i &#xff1a;指定扫描路径。-o&#xff1a;输出目录。…

【Linux:环境变量】

环境变量一般是指在操作系统中用来指定操作系统环境的一些参数 常见的环境变量&#xff1a; PATH 指定可执行程序的搜索路径 系统级的文件&#xff1a;/etc/bashrc 用户级文件&#xff1a;~/.bashrc ~/.bash_profile HOME 指定用户的主要工作目录&#xff08;当前用…

kettle从入门到精通 第六十一课 ETL之kettle 任务调度器,轻松使用xxl-job调用kettle中的job和trans

想真正学习或者提升自己的ETL领域知识的朋友欢迎进群&#xff0c;一起学习&#xff0c;共同进步。若二维码失效&#xff0c;公众号后台加我微信入群&#xff0c;备注kettle。 1、大家都知道kettle设计的job流程文件有个缺点&#xff1a;只能设置简单的定时任务&#xff0c;无法…

数据库-索引(高级篇)

文章目录 索引概念&#xff1f;索引演示&#xff1f;索引的优劣&#xff1f;为什么使用索引就快&#xff1f;本篇小结 更多相关内容可查看 索引概念&#xff1f; 索引&#xff08;index&#xff09;是帮助MySQL高效获取数据的数据结构(有序)。在数据之外&#xff0c;数据库系统…

语法分析-文法

如果对于一部文法中&#xff0c;存在至少一个句子有两个或者两个以上的语法树则该文法是二义性的。 我们可以以上面的例子进行解释&#xff0c;对于第棵个语法树&#xff0c;我们可以看到是先进行了加法运算再进行的乘法运算&#xff0c;因为需要先把EE作为整体运算完后再成为E…

上海亚商投顾:沪指低开低走 两市成交额跌破8000亿

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 市场全天震荡走低&#xff0c;三大股指尾盘均跌近1%。地产股逆势走强&#xff0c;光大嘉宝、天地源、云南城投…

幻兽帕鲁Palworld服务器手动+docker部署方法+备份迁移

目录 帕鲁部署官方文档帕鲁手动安装法手动安装steamcmd通过steamcmd安装帕鲁后端 docker容器一键部署幻兽帕鲁绿联云NAS机器部署幻兽帕鲁客户端连接附录1&#xff1a;PalServer.sh的启动项附录2&#xff1a;配置文件游戏存档保存和迁移 关于阿里云计算巢 帕鲁部署官方文档 htt…

​学者观察 | 从区块链应用创新看长安链发展——CCF区块链专委会荣誉主任斯雪明

导语 2024年1月27日&#xff0c;斯雪明教授在长安链发布三周年庆暨生态年会上发表演讲&#xff0c;认为在区块链发展过程中&#xff0c;不仅需要技术创新&#xff0c;同时需要有价值、有特色、有示范意义的应用创新。斯雪明教授介绍了国内区块链技术与应用发展的现状、趋势与挑…

【数据结构】排序(直接插入排序,希尔排序)

目录 一、排序的概念 二、常见的排序算法 三、插入排序 1.直接插入排序 1.直接插入排序实现 2.直接插入排序特性及复杂度 2.希尔排序 1.排序思路 2.希尔排序实现 3.希尔排序的特性及复杂度 一、排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#x…

python手写数字识别(PaddlePaddle框架、MNIST数据集)

python手写数字识别&#xff08;PaddlePaddle框架、MNIST数据集&#xff09; import paddle import paddle.nn.functional as F from paddle.vision.transforms import Compose, Normalizetransform Compose([Normalize(mean[127.5],std[127.5],data_formatCHW)]) # 使用tran…

[Java基础揉碎]多线程基础

多线程基础 什么是程序, 进程 什么是线程 什么是单线程,多线程 并发, 并行的概念 单核cpu来回切换, 造成貌似同时执行多个任务, 就是并发; 在我们的电脑中可能同时存在并发和并行; 怎么查看自己电脑的cpu有几核 1.资源监视器查看 2.此电脑图标右键管理- 设备管理器- 处理器…

k8s 二进制安装 详细安装步骤

目录 一 实验环境 二 操作系统初始化配置&#xff08;所有机器&#xff09; 1&#xff0c;关闭防火墙 2&#xff0c;关闭selinux 3&#xff0c;关闭swap 4, 根据规划设置主机名 5, 做域名映射 6&#xff0c;调整内核参数 7&#xff0c; 时间同步 三 部署 dock…

原生IP介绍

原生IP&#xff0c;顾名思义&#xff0c;即初始真实IP地址&#xff0c;是指从互联网服务提供商获得的IP地址&#xff0c;IP地址在互联网与用户之间直接建立联系&#xff0c;不需要经过代理服务器代理转发。 原生IP具备以下特点。 1.直接性 原生IP可以直接连接互联网&#xff…

代码随想录算法训练营第五十四天

第二题我看了很久还是没太明白&#xff0c;我发现理解动规有一点点吃力了啊&#xff0c;努努力。 392.判断子序列 总感觉在不等于的时候&#xff0c;应该是dp[i][j] dp[i-1][j-2]; 这里其实按他那个图会更好理解一点。 class Solution { public:bool isSubsequence(string s, …