携手创作,共同成长!这是我参与「掘金日新计划 · 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), 为递归过程中栈的开销
思路二: 迭代
利用栈来记录遍历的过程:
- 首先 根入栈;
- 根节点出栈,将根节点值存入数组中, 注意是使用
unshift; - 然后遍历左子树、右子树;因为栈是先进后出,所以左子树先入栈;
- 继续出栈(右子树出栈)
- 依次循环出栈遍历入栈,直到栈为空
实现代码如下:
/**
* @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)