根据一棵树的中序遍历与后序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
中序遍历 inorder = [9,3,15,20,7]
后序遍历 postorder = [9,15,7,20,3]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
解题思路
实际上这个问题和之前Leetcode 105:从前序与中序遍历序列构造二叉树(最详细的解法!!!)是一样的。所以我们使用同样策略即可。
class Solution:
def buildTree(self, inorder, postorder):
"""
:type inorder: List[int]
:type postorder: List[int]
:rtype: TreeNode
"""
if inorder:
ind = inorder.index(postorder.pop())
root = TreeNode(inorder[ind])
root.right = self.buildTree(inorder[ind+1:], postorder)
root.left = self.buildTree(inorder[:ind], postorder)
return root
注意上面写法与之前写法的区别,也就是root.right
和root.left
的前后位置问题。
同样的可以写出迭代版本。对于迭代的关键还是在于找根节点。我我们通过postorder
知道3
是整棵树的根节点,所以我们建立一个stack
,然后将3
加入到stack
中。栈顶是我们每次要考虑的根节点,我们每次从后向前遍历postorder
中的元素。我们首先考虑20
应该放在哪?通过postorder
我们知道20
一定是root右子树
的根节点,所以我们将9
加入到root(3).right
。
stack: 3 20
3
\
20
我们接着考虑7
应该放在哪。我们通过postorder
知道7
一定是20
右子树的根节点,所以我们将7
放在20
的右边。
stack: 3 20 7
3
\
20
\
7
接着寻找7
的左右孩子,我们通过inorder
推断出7
没有左右孩子。所以我们将7
出栈。
stack: 3 20
3
\
20
\
7
我们接着考虑15
应该放在哪。我们通过postorder
知道15
一定是20
左孩子的根节点。我们将15
入栈。
stack: 3 20 15
3
\
20
/ \
15 7
通过inorder
我们知道15
没有左右孩子,所以我们将15
出栈。我们发现20
的左右子树已经填满了,所以我们将20
也出栈。
stack: 3
3
\
20
/ \
15 7
我们接着考虑9
应该放在哪。我们发现3
的左边还是空的,所以我们将9
放到3
的左边。同时将9
入栈
stack: 3 9
3
/ \
9 20
/ \
15 7
接着就是具体实现上的细节。
class Solution:
def buildTree(self, inorder, postorder):
"""
:type inorder: List[int]
:type postorder: List[int]
:rtype: TreeNode
"""
if not inorder or not postorder:
return
postorder.reverse()
root = TreeNode(postorder[0])
stack = [root]
i = len(inorder) - 1
for node in postorder[1:]:
parent = stack[-1]
if parent.val != inorder[i]:
parent.right = TreeNode(node)
stack.append(parent.right)
else:
while stack and stack[-1].val == inorder[i]:
parent = stack.pop()
i -= 1
parent.left = TreeNode(node)
stack.append(parent.left)
return root
我将该问题的其他语言版本添加到了我的GitHub Leetcode
如有问题,希望大家指出!!!