145. 二叉树的后序遍历
题目来源:力扣(LeetCode)
https://leetcode-cn.com/problems/binary-tree-postorder-traversal
题目
给定一个二叉树,返回它的 后序 遍历。
示例:
输入: [1,null,2,3]
1
\
2
/
3
输出: [3,2,1]
进阶: 递归算法很简单,你可以通过迭代算法完成吗?
解题思路
思路:递归、迭代
开篇这里引用一段文字叙述,来简单说明下树遍历:
The general recursive pattern for traversing a (non-empty) binary tree is this: At node N you must do these three things:
- (L) recursively traverse its left subtree. When this step is finished you are back at N again.
- ® recursively traverse its right subtree. When this step is finished you are back at N again.
- (N) Actually process N itself.
We may do these things in any order and still have a legitimate traversal. If we do (L) before ®, we call it left-to-right traversal, otherwise we call it right-to-left traversal.
Pre-Order Traversal
- do (N) before anything else.
Post-Order Traversal
- do (N) after everything else.
In-Order, or Infix Order, Traversal
- do (N) in between the two subtrees.
上面文字前面部分的叙述,大致的意思如下:
递归遍历二叉树(非空)时,假设当前节点为 N,这里需要做的有三件事:
- 递归遍历 N 节点的左子树。递归结束后返回到 N 节点;
- 递归遍历 N 节点的右子树。递归结束后返回到 N 节点;
- 还有就是真正意义上的处理 N 节点的数据。
这里我们可以发现 N 节点并非只被访问一次,但是对于节点数据的处理则只有一次。
而后面部分,则说明 前序遍历、后序遍历 及 中序遍历 三者的区别。
前序遍历
- 在递归左右子树之前,处理节点数据。
后序遍历
- 在递归左右子树之后,处理节点数据。
中序遍历
- 在递归左子树之后,递归右子树之前,处理节点数据。
这里额外提下,关于 前序遍历 及 中序遍历 的题目如下:
递归
根据前面的叙述,我们可以发现使用递归的方法 可以简单的实现。具体代码如下:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def postorderTraversal(self, root: TreeNode) -> List[int]:
def helper(root):
if not root:
return
# 递归左子树
helper(root.left)
# 递归右子树
helper(root.right)
# 在递归完左右子树之后,处理节点数据
ans.append(root.val)
ans = []
helper(root)
return ans
迭代
题目中进阶部分,要求使用迭代的方法实现。那么我们这里可以显示调用栈模拟递归。
具体的代码如下:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def postorderTraversal(self, root: TreeNode) -> List[int]:
if not root:
return []
ans = []
stack = []
stack.append(root)
while stack:
node = stack.pop()
if node:
# 如果节点不为空,
# 当前节点重新入栈
stack.append(node)
# 这里添加 None,为了后面处理数据,
# 标记左右子节点访问结束,可处理当前节点
stack.append(None)
# 这里先将右子节点入栈
if node.right:
stack.append(node.right)
# 再将左子节点入栈
if node.left:
stack.append(node.left)
else:
node = stack.pop()
ans.append(node.val)
return ans
引用
- “Lecture 8, Tree Traversal”. Retrieved 29 Sep 2020.
欢迎关注
公众号 【书所集录】