LeetCode 144. Binary Tree Preorder Traversal

本文探讨了二叉树的先序遍历算法,包括递归、迭代及改进的迭代方法。递归方法直观但空间复杂度高,迭代方法减少资源消耗,改进的迭代方法则更高效地遍历左子树。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem

题目链接

Solution

给定一棵二叉树,输出其先序(preorder)遍历结果。
想法有三
第一种,递归版本。因为二叉树的遍历定义其实就是一种递归形式的定义,因此很好想到对应代码。但是递归有一个问题,产生的空间复杂度比较高,因为系统栈每次都会把所有变量都临时保存,会产生很多的重复。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> ans;
    vector<int> preorderTraversal(TreeNode* root) {
        if(root==NULL) return ans;
        ans.push_back(root->val);
        preorderTraversal(root->left);
        preorderTraversal(root->right);
        return ans;
    }
};

第二种,把递归改成迭代,可以减小时间、空间复杂度的常系数。因为先序遍历的递归十分类似于尾递归,那么我们可以用消除尾递归的方法直接改写成遍历版本1。这个遍历版本其实就是模拟了递归版本的系统堆栈的工作过程。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> ans;
        if(root) st.push(root);
        while(!st.empty()){
            TreeNode* p=st.top();
            st.pop();
            ans.push_back(p->val);
            if(p->right) st.push(p->right);
            if(p->left) st.push(p->left);
        }
        return ans;
    }
};

第三种,众所周知,二叉树的遍历除了preorder,还有inorder、postorder。preorder的递归版本可以看成尾递归,但是另外两种的递归版本(也很好写,只是改变一下访问值语句的位置就可以了)就无法根据尾递归消除的规则来改写成迭代版本了。
这时我们必须换种思路,通过下图,我们可以总结出先序遍历的一种方法,先沿着左边自顶向下访问左边节点,然后再自底向下遍历这些节点的右子树。若某节点右子树不存在为空,则继续返回到上一个节点再看右子树是否存在;若某节点右子树存在,那么对该右子树也是同样的遍历规则,先访问最左边的那些节点…(重复上述过程)。该思想可以在inorder、postorder也有用武之地。
在这里插入图片描述

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    void visitleft(TreeNode *x,stack<TreeNode*> &st,vector<int> &ans){
        while(x)
        {
            ans.push_back(x->val);
            st.push(x->right);
            x=x->left;
        }
        return;
    }
    vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> ans;
        TreeNode *p=root;
        while(true)
        {
            visitleft(p,st,ans);
            if(st.empty()) break;
            p=st.top();
            st.pop();
        }
        return ans;
    }
};

Results

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值