【刷题记录】关于二叉树的OJ题(下)

简介: 【刷题记录】关于二叉树的OJ题(下)

6.二叉树的遍历


**题目链接 144. 二叉树的前序遍历 **

题干

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

示例1

inorder_1.jpg

输入:root = [1,null,2,3]
输出:[1,2,3]

示例2

输入:root = []
输出:[]


题目分析:

这个题使用递归的方式实现是非常轻松的,这里就不过多赘述,我们主要来理解迭代的思想使用迭代的方式解决此问题

改写迭代的重要性:递归的深度越深,消耗的资源越多,这个资源是在栈上的,而对于目前的操作系统来说,栈上的空间是很小的,大概只有8M左右,所以很容易出现栈溢出的问题,即使代码是没有问题的,也不一定能运行,相对于栈来说,堆上的空间就大很多了,所以一般将递归改写成迭代。

这里如果想要用迭代的方法遍历,就需要借助数据结构的栈来实现。我们来分析一下前序遍历的过程。对于任意一颗二叉树来说,可以分为左路节点和左路节点的右子树,首先就是根节点,然后是左子树的根,然后左子树的左子树,一直走下去,直到左子树为空然后走这个子树的右子树,右子树走完之后再回到上一个根的位置,再走右子树,直到回到整棵树的根节点为止。所以这里遵循后进先出的规则,因此我们借助栈来实现迭代的改写。


代码实现

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> preorder;
        stack<TreeNode*> st;
        TreeNode* cur = root;
        while(cur || !st.empty())
        {
            //开始遍历一棵树,根节点为cur
            while(cur)//遍历左路节点并入栈
            {
                st.push(cur);
                preorder.push_back(cur->val);
                cur = cur->left;
            }
            //cur现在指向二叉树的最左节点,下一步出栈,并处理右子树
            TreeNode* top = st.top();
            st.pop();
            cur = top->right;//处理右子树
        }
        return preorder;
    }
};


截屏2023-05-08 08.02.22.png


**拓展1**:

94. 二叉树的中序遍历 递归解法

中序遍历与前序遍历类似,只是中序序列push_back的时候,不能先push根节点,而是在处理完左子树之后在push,所以代码示例如下

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> inorder;
        TreeNode* cur = root;
        while(cur || !st.empty())
        {
            while(cur)
            {
                st.push(cur);
                cur = cur->left;
            }
            TreeNode* top = st.top();
            st.pop();
            inorder.push_back(top->val);//这里是在处理右子树之前push_back
            cur = top->right;
        }
        return inorder;
    }
};

截屏2023-05-08 08.26.29.png

拓展2

145. 二叉树的后序遍历 递归解法

同样的大思路,但是细节的地方还是要做一些修改。后续遍历要求访问完左右子树之后再访问根节点。分析过程可知,按照此思路走对于任意的右子树,将会访问两遍,分别是在此树访问右子树前和访问右子树后,这里要判断一下是否已经访问过了,如果访问过了就直接访问根,否则就访问右子树

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> postorder;
        TreeNode* cur = root;
        TreeNode* prev = nullptr;//这里使用一个prev保存上一个访问的节点
        while(cur || !st.empty())
        {
            while(cur)
            {
                st.push(cur);
                cur = cur->left;
            }
            TreeNode* top = st.top();
//这里对右子树是否访问过的判断方法是判断上一个访问的节点是否是右子树,也可以使用其他方法,例如stack<pair<TreeNode*, bool>>
            if(top->right == nullptr || top->right == prev)//当右子树为空或者右子树已经访问过
            {
                st.pop();
                postorder.push_back(top->val);//访问根
                prev = top;//记录上一个访问节点
            }
            else//右子树没有被访问过,迭代访问右子树
                cur = top->right;
        }
        return postorder;
    }
};

截屏2023-05-08 08.49.48.png

这道题还有一个比较清奇的解法,就是按照类似前序遍历的方式,但是需要先遍历右子树,即根节点->右子树->左子树的顺序遍历一遍,也就是改写一下上述前序的方法,然后最终的结果reverse一下就是后序遍历序列,这里提供一下思路,有兴趣的可以试一下

相关文章
|
5天前
|
云安全 人工智能 安全
AI被攻击怎么办?
阿里云提供 AI 全栈安全能力,其中对网络攻击的主动识别、智能阻断与快速响应构成其核心防线,依托原生安全防护为客户筑牢免疫屏障。
|
15天前
|
域名解析 人工智能
【实操攻略】手把手教学,免费领取.CN域名
即日起至2025年12月31日,购买万小智AI建站或云·企业官网,每单可免费领1个.CN域名首年!跟我了解领取攻略吧~
|
9天前
|
安全 Java Android开发
深度解析 Android 崩溃捕获原理及从崩溃到归因的闭环实践
崩溃堆栈全是 a.b.c?Native 错误查不到行号?本文详解 Android 崩溃采集全链路原理,教你如何把“天书”变“说明书”。RUM SDK 已支持一键接入。
590 212
|
4天前
|
编解码 Linux 数据安全/隐私保护
教程分享免费视频压缩软件,免费视频压缩,视频压缩免费,附压缩方法及学习教程
教程分享免费视频压缩软件,免费视频压缩,视频压缩免费,附压缩方法及学习教程
236 138
|
存储 人工智能 监控
从代码生成到自主决策:打造一个Coding驱动的“自我编程”Agent
本文介绍了一种基于LLM的“自我编程”Agent系统,通过代码驱动实现复杂逻辑。该Agent以Python为执行引擎,结合Py4j实现Java与Python交互,支持多工具调用、记忆分层与上下文工程,具备感知、认知、表达、自我评估等能力模块,目标是打造可进化的“1.5线”智能助手。
828 60
|
7天前
|
人工智能 移动开发 自然语言处理
2025最新HTML静态网页制作工具推荐:10款免费在线生成器小白也能5分钟上手
晓猛团队精选2025年10款真正免费、无需编程的在线HTML建站工具,涵盖AI生成、拖拽编辑、设计稿转代码等多种类型,均支持浏览器直接使用、快速出图与文件导出,特别适合零基础用户快速搭建个人网站、落地页或企业官网。
1226 157
|
6天前
|
存储 安全 固态存储
四款WIN PE工具,都可以实现U盘安装教程
Windows PE是基于NT内核的轻量系统,用于系统安装、分区管理及故障修复。本文推荐多款PE制作工具,支持U盘启动,兼容UEFI/Legacy模式,具备备份还原、驱动识别等功能,操作简便,适合新旧电脑维护使用。
515 109