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

《代码随想录》刷题打卡day11:二叉树part01

文章目录

    • 1. 二叉树基础理论
    • 2. 题目打卡
      • DFS:
        • 144.二叉树的前序遍历
        • 145.二叉树的后序遍历
        • 94.二叉树的中序遍历
        • 递归法:
        • 迭代法:
        • 统一迭代法
      • BFS
        • 102.二叉树的层序遍历
        • 107.二叉树的层次遍历
        • 199.二叉树的右视图
        • 637.二叉树的层平均值
        • 429.N叉树的层序遍历
        • 515.在每个树行中找最大值
        • 116.填充每个节点的下一个右侧节点指针
        • 117.填充每个节点的下一个右侧节点指针II
        • 104.二叉树的最大深度
        • 111.二叉树的最小深度

1. 二叉树基础理论

二叉树种类:

满二叉树、完全二叉树(仅底层节点未填满,未填满的话节点必须在左边)

二叉搜索树(值:左>中>右)、平衡二叉搜索树(左右子树深度差不超过1)

二叉树存储方式

链式存储&顺序存储

链式存储图:

顺序存储图:

二叉树的遍历方式:

  • 深度优先遍历

    • 前序遍历(递归法,迭代法)
    • 中序遍历(递归法,迭代法)
    • 后序遍历(递归法,迭代法)

  • 广度优先遍历

    • 层次遍历(迭代法)

二叉树的定义

structTreeNode{intval;TreeNode*left;TreeNode*right;TreeNode(intx):val(x),left(nullptr),right(nullptr){}};

2. 题目打卡

DFS:

144.二叉树的前序遍历
145.二叉树的后序遍历
94.二叉树的中序遍历
递归法:

递归算法的三个要素。每次写递归,都按照这三要素来写,可以保证大家写出正确的递归算法!

  1. 确定递归函数的参数和返回值:确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。

  2. 确定终止条件:写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。

  3. 确定单层递归的逻辑:确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。

    classSolution{//前序遍历public:voidtraversal(TreeNode*cur,vector<int>&vec){if(cur==NULL)return;vec.push_back(cur->val);// 中traversal(cur->left,vec);// 左traversal(cur->right,vec);// 右}vector<int>preorderTraversal(TreeNode*root){vector<int>result;traversal(root,result);returnresult;}};
迭代法:
  1. 前序遍历:是中左右,每次先处理的是中间节点,那么先将根节点放入栈中,然后将右孩子加入栈,再加入左孩子。
    为什么要先加入 右孩子,再加入左孩子呢? 因为这样出栈的时候才是中左右的顺序。

    classSolution{public:vector<int>preorderTraversal(TreeNode*root){stack<TreeNode*>st;vector<int>result;if(root==NULL)returnresult;st.push(root);while(!st.empty()){TreeNode*node=st.top();// 中st.pop();result.push_back(node->val);if(node->right)st.push(node->right);// 右(空节点不入栈)if(node->left)st.push(node->left);// 左(空节点不入栈)}returnresult;}};
  2. 中序遍历:为了解释清楚,我说明一下 刚刚在迭代的过程中,其实我们有两个操作:
    处理:将元素放进result数组中
    访问:遍历节点
    分析一下为什么刚刚写的前序遍历的代码,不能和中序遍历通用呢,因为前序遍历的顺序是中左右,先访问的元素是中间节点,要处理的元素也是中间节点,所以刚刚才能写出相对简洁的代码,因为要访问的元素和要处理的元素顺序是一致的,都是中间节点。
    那么再看看中序遍历,中序遍历是左中右,先访问的是二叉树顶部的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点(也就是在把节点的数值放进result数组中),这就造成了
    处理顺序和访问顺序是不一致的。

    那么在使用迭代法写中序遍历,就需要借用指针的遍历来帮助访问节点,栈则用来处理节点上的元素。

    classSolution{public:vector<int>inorderTraversal(TreeNode*root){vector<int>result;stack<TreeNode*>st;TreeNode*cur=root;while(cur!=NULL||!st.empty()){if(cur!=NULL){// 指针来访问节点,访问到最底层st.push(cur);// 将访问的节点放进栈cur=cur->left;// 左}else{cur=st.top();// 从栈里弹出的数据,就是要处理的数据(放进result数组里的数据)st.pop();result.push_back(cur->val);// 中cur=cur->right;// 右}}returnresult;}};
  3. 后序遍历:再来看后序遍历,先序遍历是中左右,后序遍历是左右中,那么我们只需要调整一下先序遍历的代码顺序,就变成中右左的遍历顺序,然后在反转result数组,输出的结果顺序就是左右中了。

统一迭代法

就是要处理的节点放入栈之后,紧接着放入一个空指针作为标记。这种方法可以叫做空指针标记法

classSolution{//中序遍历public:vector<int>inorderTraversal(TreeNode*root){vector<int>result;stack<TreeNode*>st;if(root!=NULL)st.push(root);while(!st.empty()){TreeNode*node=st.top();if(node!=NULL){st.pop();// 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中if(node->right)st.push(node->right);// 添加右节点(空节点不入栈)st.push(node);// 添加中节点st.push(NULL);// 中节点访问过,但是还没有处理,加入空节点做为标记。if(node->left)st.push(node->left);// 添加左节点(空节点不入栈)}else{// 只有遇到空节点的时候,才将下一个节点放进结果集st.pop();// 将空节点弹出node=st.top();// 重新取出栈中元素st.pop();result.push_back(node->val);// 加入到结果集}}returnresult;}};

BFS

classSolution{public:vector<vector<int>>levelOrder(TreeNode*root){queue<TreeNode*>que;if(root!=NULL)que.push(root);vector<vector<int>>result;while(!que.empty()){intsize=que.size();vector<int>vec;// 这里一定要使用固定大小size,不要使用que.size(),因为que.size是不断变化的for(inti=0;i<size;i++){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);}returnresult;}};
102.二叉树的层序遍历
107.二叉树的层次遍历
199.二叉树的右视图
637.二叉树的层平均值
429.N叉树的层序遍历
515.在每个树行中找最大值
116.填充每个节点的下一个右侧节点指针
117.填充每个节点的下一个右侧节点指针II
104.二叉树的最大深度
111.二叉树的最小深度
http://www.jsqmd.com/news/987665/

相关文章:

  • 警惕“拿着 AI 找场景”:伪需求下的 Agent 泡沫
  • 洛阳商标代办哪家靠谱?选叮咚知多多,专业合规更省心 - 中媒介
  • MySQL 8.0实战:一条SQL搞定用户签到统计(INSERT ... ON DUPLICATE KEY UPDATE详解)
  • [charger][sc7061]配置
  • 宁波10个高端楼盘石材装修实景案例合集(2026版) - 宁波融诚石业
  • 告别鼠标手!Kicad 6.0 原理图与PCB设计最全快捷键清单(附PDF速查表)
  • 别再手动整理代码了!用IDEA的Save Actions插件实现保存即格式化(附避坑配置)
  • Apollo配置中心踩坑记:从IDE变量到Server.properties,优先级与缓存那些事儿
  • 高性能计算中的输出重定向:Bash与SLURM的协同工作
  • Spring AI实战:快速集成阿里通义千问
  • 用 Vim 以只读模式打开文件的几种方式
  • 道里正规商家榜单,收的顶领跑区域黄金回收行业 - 奢侈品回收测评
  • # 高并发核心系统中分布式事务一致性架构演进实践
  • 助睿Max数据大屏实战(进阶篇):浏览器用户画像大屏的数据接入与交互全解析
  • 哈尔滨道里高价回收店铺TOP榜,2026黄金回收收的顶稳居榜首梯队 - 奢侈品回收测评
  • UVM验证进阶:如何像搭积木一样,用start_item和finish_item组合出灵活的激励流?
  • 别再死记硬背了!用STM32CubeMX+FreeModbus库,5分钟搞定你的第一个Modbus从机
  • 维特比译码在5G和Wi-Fi 6里到底怎么用的?从仿真到硬件实现的跨越
  • 宁波石材加工厂怎么选?本地源头工厂7个筛选标准(2026版) - 宁波融诚石业
  • 别再只盯着TPM了!从国产TPCM实战出发,聊聊可信启动的静态度量与动态度量到底怎么玩
  • 别再只用VAE了!CTGAN vs TVAE:手把手教你为表格数据选对生成模型
  • 2026年 大庆/黑龙江GEO优化服务商推荐榜:豆包GEO推广与AI获客关键词优化全景解析 - 品牌发掘
  • 告别混乱!用SAP PS用户状态与字段选择,搭建清晰的项目管理流程(附SU22/SU24配置技巧)
  • 苏州五年制专转本美术大类,选择蓝洋教育的核心理由 - 起跑123
  • 用CppAD+IPOPT搞定一个简单的非线性优化问题:从数学公式到C++代码的完整流程
  • 通关‘头歌’线性回归后,我总结了5个NumPy实战技巧与1个常见坑
  • FastAPI学习笔记:二、ORM
  • 后端技术栈深度解析:从入门到精通的完整指南
  • 后端技术栈实战指南:打造高性能、高可用系统
  • 2026年 除漆剂/除臭剂/絮凝剂/消泡剂厂家推荐榜:源头工艺与环保高效除味消泡实力品牌解析 - 品牌发掘