【刷题记录】关于二叉树的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一下就是后序遍历序列,这里提供一下思路,有兴趣的可以试一下

相关文章
|
12天前
|
数据采集 人工智能 安全
|
8天前
|
编解码 人工智能 自然语言处理
⚽阿里云百炼通义万相 2.6 视频生成玩法手册
通义万相Wan 2.6是全球首个支持角色扮演的AI视频生成模型,可基于参考视频形象与音色生成多角色合拍、多镜头叙事的15秒长视频,实现声画同步、智能分镜,适用于影视创作、营销展示等场景。
597 4
|
8天前
|
机器学习/深度学习 人工智能 前端开发
构建AI智能体:七十、小树成林,聚沙成塔:随机森林与大模型的协同进化
随机森林是一种基于决策树的集成学习算法,通过构建多棵决策树并结合它们的预测结果来提高准确性和稳定性。其核心思想包括两个随机性:Bootstrap采样(每棵树使用不同的训练子集)和特征随机选择(每棵树分裂时只考虑部分特征)。这种方法能有效处理大规模高维数据,避免过拟合,并评估特征重要性。随机森林的超参数如树的数量、最大深度等可通过网格搜索优化。该算法兼具强大预测能力和工程化优势,是机器学习中的常用基础模型。
345 164
|
7天前
|
机器学习/深度学习 自然语言处理 机器人
阿里云百炼大模型赋能|打造企业级电话智能体与智能呼叫中心完整方案
畅信达基于阿里云百炼大模型推出MVB2000V5智能呼叫中心方案,融合LLM与MRCP+WebSocket技术,实现语音识别率超95%、低延迟交互。通过电话智能体与座席助手协同,自动化处理80%咨询,降本增效显著,适配金融、电商、医疗等多行业场景。
349 155

热门文章

最新文章