题目
145. 二叉树的后序遍历
难度:困难
题目分析:如果采用递归的方法,那难度其实等于0。
对于后序遍历来说,最难的其实是迭代的方法。因为后序遍历的顺序是 左-右-根,这意味着,找到最左的叶子之后,还要再往右边可能的叶子找,最后才能输出根节点位置的值。
2. 解法一:递归
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def postorderTraversal(self, root: TreeNode) -> List[int]:
# 递归
res = []
def dfs(root):
if not root:
return
dfs(root.left)
dfs(root.right)
res.append(root.val)
dfs(root)
return res
2.1 运行结果
3.解法三:第二种递归方法
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def postorderTraversal(self, root: TreeNode) -> List[int]:
# 第二种递归的方法
if not root:
return []
res = []
res += self.postorderTraversal(root.left)
res += self.postorderTraversal(root.right)
res.append(root.val)
return res
3.1 运行结果:
3.2 分析:
之前根据别人的模板,完全忽略了可以不用额外定义函数,而直接进行递归。
这里的速度和内存占用,跟之前的方法差别不大。
在代码的组织上,具备了递归程序的一切优点。建立空列表,然后把左子树后序遍历结果附上;再附上右子树后序遍历的结果;最后附上根节点的值。
4. 解法三:迭代的方法
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def postorderTraversal(self, root: TreeNode) -> List[int]:
# 运用迭代的方法求解
res, stack = [], []
while stack or root:
while root:
stack.append(root)
root = root.left if root.left else root.right
# 跳出循环后,说明已经走到最下面,可以读取
node = stack.pop()
res.append(node.val)
if stack and node == stack[-1].left:
root = stack[-1].right
else:
root = None
return res
4.1 运行结果:
4.2 分析:
还好,通过回忆还能正确写出迭代的算法。
这里的关键是第二个while循环,不仅要一直沿着左子树前进,当左子树为空时,就要切换成右子树,然后继续往左前进。
跳出 while 循环的时候,一定是最左侧的叶节点了。于是,这个点的数据可以读取。
接下来是难点。此时栈顶存储的元素是该叶节点的父节点,我们要判断已经记录的点是该父节点的左子树还是右子树。
如果是左子树,意味父节点还不能弹出,root 的值要设为父节点的右子树,继续进行探索。
如果是右子树,则说明父节点的值可以读取。此时,设root为None, 根据程序逻辑,就会自动弹出父节点进行读取。