145. 二叉树的后序遍历

104 阅读1分钟

leetcode.cn/problems/bi…

给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 。

 

示例 1:

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

输入:root = [] 输出:[] 示例 3:

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

提示:

树中节点的数目在范围 [0, 100] 内 -100 <= Node.val <= 100  

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

递归

解题思路

首先我们需要了解什么是二叉树的后序遍历:按照访问左子树——右子树——根节点的方式遍历这棵树,而在访问左子树或者右子树的时候,我们按照同样的方式遍历,直到遍历完整棵树。因此整个遍历过程天然具有递归的性质,我们可以直接用递归函数来模拟这一过程。

定义 postorder(root) 表示当前遍历到 root 节点的答案。按照定义,我们只要递归调用 postorder(root->left) 来遍历 root 节点的左子树,然后递归调用 postorder(root->right) 来遍历 root 节点的右子树,最后将 root 节点的值加入答案即可,递归终止的条件为碰到空节点。

复杂度分析

image.png

代码

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        recur(root, list);
        return list;
    }

    public void recur(TreeNode root, List<Integer> list) {
        if (root == null) {
            return;
        }
        recur(root.left, list);
        recur(root.right, list);
        list.add(root.val);
    }
}

迭代

解题思路

我们也可以用迭代的方式实现方法一的递归函数,两种方式是等价的,区别在于递归的时候隐式地维护了一个栈,而我们在迭代的时候需要显式地将这个栈模拟出来,其余的实现与细节都相同,具体可以参考下面的代码。

复杂度分析

image.png

代码

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        if (root == null) {
            return list;
        }
        Stack<TreeNode> stack = new Stack<>();
        TreeNode pre = null;
        while (root != null || !stack.isEmpty()) {
            while (root != null) {
                stack.push(root);
                root = root.left;
            }
            root = stack.pop();
            if (root.right == null || pre == root.right) {
                list.add(root.val);
                pre = root;
                root = null;
            } else {
                stack.push(root);
                root = root.right;
            }
        }
        return list;
    }
}