【Hot 100 刷题计划】 LeetCode 94. 二叉树的中序遍历 | C++ 递归法 & 迭代法

LeetCode 94. 二叉树的中序遍历

📌 题目描述

题目级别:简单

给定一个二叉树的根节点 root ,返回 它的 中序 遍历。

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

💡 解法一:递归的本质

二叉树的中序遍历规则非常简单:左子树 -> 根节点 -> 右子树

因为树本身就是一个天然的递归结构(每一个子节点都可以看作是一棵新树的根),所以使用递归解法最符合直觉:

  1. 先一头扎进左子树,直到最底端。
  2. 处理当前节点(将值放入结果数组)。
  3. 再一头扎进右子树。

细节优化:

为了防止在递归过程中不断创建新的结果数组,我们只需在主函数创建一次 vector<int> res,然后通过引用传递 &res 把它交由递归函数去填充。这样极大提升了内存效率。


💻 C++ 代码实现 (递归法)

cpp 复制代码
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        // 将 res 以引用方式传入,避免拷贝
        inorder(root, res);
        return res;
    }

    void inorder(TreeNode* root, vector<int>& res)
    {
        // 递归终止条件:遇到空节点直接返回
        if (!root) return ;

        // 1. 遍历左子树
        inorder(root -> left, res);
        
        // 2. 访问根节点:将节点值存入结果
        res.push_back(root -> val);
        
        // 3. 遍历右子树
        inorder(root -> right, res);
    }
};

💡 解法二:用 Stack 手动模拟系统栈

在递归写法中,程序之所以能从底层一路"退回来",是因为操作系统帮我们在底层维护了一个"函数调用栈"。

如果要求用迭代(循环)来实现,我们就必须自己动手建一个栈 (stack) 来模拟这个回退的过程

核心运作机制(一路向左,撞墙回头):

  1. 准备一个指针 curr 指向根节点。
  2. "一路向左" :只要 curr 不为空,我们就一直顺着左子树往下走,同时把路过的节点统统压入栈中。(因为中序遍历要最后才访问这些父节点,所以先用栈把它们存起来)。
  3. "撞墙回头" :当 curr 走到空(碰壁了),说明左边到底了。这时候我们就从栈顶弹出一个节点,这个节点就是没有左孩子(或者左孩子已经被访问过)的最底层的节点
  4. "访问与向右" :把弹出的节点值加入结果数组。既然它的左边和自己都已经处理完了,接下来就让 curr 指向它的右孩子,准备开启下一轮同样的循环。

💻 C++ 代码实现 (栈迭代法)

cpp 复制代码
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> st;  // 我们自己维护的调用栈
        TreeNode* curr = root; // 游标指针

        // 循环条件:只要游标还没走完,或者栈里还有没处理完的节点,就继续
        while (curr != nullptr || !st.empty()) {
            
            // 阶段 1:不断向左深入,把沿途的节点统统压栈
            while (curr != nullptr) {
                st.push(curr);
                curr = curr->left;
            }
            
            // 阶段 2:此时 curr 为空,说明左边走到底了
            // 从栈顶取出一个节点(退回上一步)
            curr = st.top();
            st.pop();
            
            // 访问该节点:存入结果数组
            res.push_back(curr->val);
            
            // 阶段 3:转向该节点的右子树,继续下一轮外层大循环
            curr = curr->right;
        }

        return res;
    }
};
相关推荐
罗西的思考16 分钟前
机器人模型(WM / WAM / VLA)综合分析与对比:从「看」到「想」再到「做」
人工智能·算法·机器学习
小哈里1 小时前
【知识】从学科到实践:自然・工程・社科・人文|算法・研发・产品・品牌设计
程序人生·算法·产品·设计·工程
小π军2 小时前
最大重叠区间数量
数据结构·算法
镜像视界(浙江)科技有限公司2 小时前
《视频孪生之上:二维展示终结,三维空间计算重构城市逻辑》——跨摄像连续表达 × 三角测量厘米级定位 × 动态轨迹建模,构建新一代城市空间
大数据·人工智能·算法·矩阵·音视频·空间计算
a187927218313 小时前
【算法】双指针与滑动窗口(二):滑动窗口——吃进、判定、吐出
算法·leetcode·双指针·滑动窗口·原理·模板·算法讲解
铭哥的编程日记3 小时前
从一道 LeetCode Hard 到吃透一类题:加权区间调度「排序 + 二分 + DP」
算法·leetcode·职场和发展
Navigator_Z3 小时前
LeetCode //C - 1248. Count Number of Nice Subarrays
c语言·算法·leetcode
wzdark4 小时前
多维数组在算法设计中的存储映射问题4
算法
Phil3235 小时前
多智能体不是越多越好:Google《Towards a Science of Scaling Agent Systems》论文深度解读
算法
6Hzlia5 小时前
【Classic 150 刷题计划】 LeetCode 26. 删除有序数组中的重复项 | C++ 快慢双指针经典模板
c++·算法·leetcode