LeetCode 刷题 [C++] 第145题. 二叉树的后序遍历 (递归与迭代)

给定一个二叉树,返回它的后序遍历。

示例:
输入: [1,null,2,3]
1
\
2
/
3
输出: [3,2,1]

进阶: 递归算法很简单,你可以通过迭代算法完成吗?

二叉树的中序遍历:先左子树,接着是右子树,然后树根。

递归法

找最近简单子问题:每到一个节点N,首先遍历该节点的左子树,接着遍历右子树,然后访问节点本身;
结束条件为:当前节点为空。

解题步骤
1.先将左子树的节点值放入容器;
2.接着将右子树的节点值放入容器;
3.最后将根节点值放入容器.

递归代码模板
递归结束条件、处理当前层逻辑、下到下一层、清理当前层(非必须)。
具体代码实现

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        if(!root) return postVec;
        postorderTraversal(root->left);
        postorderTraversal(root->right);
        postVec.emplace_back(root->val);
        return postVec;
    }
private:
    vector<int> postVec;
};

AC结果
在这里插入图片描述

迭代法

迭代法一
由于后序遍历顺序是左、右、根,其逆序则为根、右、左。因此,可以先以根、右、左的顺序遍历整个二叉树(此时与前序遍历相似);然后将遍历后的结果进行逆序。
即每到一个节点N,先访问它。接着将N的左子树压入栈,然后遍历右子树。遍历完整棵树后,将结果序列逆序。

解题步骤
1.先将节点本身的值放入容器;
2.接着将左子节点放入栈中;
3.然后遍历右子树节点,即更新右子树节点为当前节点;
4.当右子树遍历到叶节点后,开始弹出该栈顶元素;
5.若栈中弹出的元素非空,则执行1~4;若为空,则不进行任何处理,继续弹出栈顶元素;
6.直至站内元素和当前元素为空,此时,对容器进行逆序,然后返回逆序后的结果即可。

具体代码实现

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        if(!root) return {};
        stack<TreeNode*> postStk;
        vector<int> postVec;
        TreeNode* current = root; 
        while(current || postStk.size()) {
            while(current) {
                postVec.emplace_back(current->val);
                postStk.push(current->left);
                current = current->right;
            }
            current = postStk.top();
            postStk.pop();
        }
        reverse(postVec.begin(),postVec.end());
        return postVec;
    }
};

AC结果
在这里插入图片描述
迭代法二
每到一个节点N,因为根要最后访问,因此将其入栈。接着遍历左子树,然后遍历右子树,最后返回到N。
这里主要一个难点是,如何区分是从左子树返回,还是从右子树返回。
为解决这个问题,需要给N节点附加一个标记F,默认初始化F为false。只有在访问节点N的右子树的时候,才将N节点的标记F置为true;而访问左子树的时候,不对标记F做任何操作,即F为默认值false。因此,在访问子树返回时,若标记F为true表示从右子树返回,否则从左子树返回。
当F为false时,表示N的左子树遍历完,还要访问右子树。
当F为true时,表示N的两棵子树都遍历过了,要访问节点N了。并且在N访问完后,N这棵子树都访问完成了。

解题步骤
1.将当前节点入栈,并更新当前节点为左子树根节点,直至左子树根节点为空;
2.然后访问右子树节点,此时将标记F置为true;
3.当栈顶元素的标记F置为true时,访问该节点,并弹出栈。
4.循环执行步骤1~3,直至栈为空。

具体代码实现

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        if(!root) return {};
        unordered_map<TreeNode*,int> work;
        stack<TreeNode*> postStk;
        vector<int> postVec;
        TreeNode* current = root; 
        while(current || postStk.size()) {
            while(current) {
                postStk.push(current);
                current = current->left;
            }
            while(postStk.size() && work[postStk.top()]) {
                postVec.emplace_back(postStk.top()->val);
                postStk.pop();
            }
            if(postStk.size()) {
                current = postStk.top()->right;
                work[postStk.top()] = 1;
            }
        }
        return postVec;
    }
};

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页