LeedCode 145:二叉树的后序遍历

158 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第27天,点击查看活动详情

LeedCode 145:二叉树的后序遍历

题目描述:

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

示例1

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

输出: [3,2,1]

解题思路 

二叉树的后序遍历:
按照访问左子树——右子树——根节点的方式遍历这棵树

思路一: 递归

定义 postorderTraversalNode(node)函数 表示当前遍历到 node 节点的结果。按照定义,我们只要递归调用 postorderTraversalNode(node.left) 来遍历 node 节点的左子树,然后递归调用 postorderTraversalNode(node.right) 来遍历 node 节点的右子树,最后将 node 节点的值加入result即可,递归终止的条件为碰到空节点

实现代码如下:

/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var postorderTraversal = function (root) {
  var result = [];
  var postorderTraversalNode = function (node) {
    if (node) {
      // 先遍历左子树
      postorderTraversalNode(node.left);
      // 再遍历右子树
      postorderTraversalNode(node.right);
      // 最后根节点
      result.push(node.val);
    }
  }
  postorderTraversalNode(root);
  return result;
};

时间复杂度: O(n),其中 n 是二叉树的节点数

空间复杂度: O(n), 为递归过程中栈的开销

思路二: 迭代

利用栈来记录遍历的过程:

  1. 首先 根入栈;
  2. 根节点出栈,将根节点值存入数组中, 注意是使用unshift
  3. 然后遍历左子树、右子树;因为栈是先进后出,所以左子树先入栈;
  4. 继续出栈(右子树出栈)
  5. 依次循环出栈遍历入栈,直到栈为空

实现代码如下:


/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var postorderTraversal = function (root) {
  var result = [], stack = [];
  if (root) stack.push(root);
  while (stack.length) {
    var node = stack.pop();

    result.unshift(node.val);
    // 先左子树进栈然后右子树
    // 出栈顺序就变更为先右后左

    if (node.left !== null) {
      stack.push(node.left);
    }
    if (node.right !== null) {
      stack.push(node.right);
    }
  }
  return result;
};

时间复杂度: O(n),其中 n 是二叉树的节点数

空间复杂度: O(n),为迭代过程中显式栈的开销,平均情况下为 O(logn),最坏情况下树呈现链状,为 O(n)

参考资料

二叉树的后序遍历 - 力扣(LeetCode)