根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
解题思路
这是一个非常基础的问题。我们考虑这样一个简单的例子
preorder = [3,9,20,15,7]
inorder = [9,3,15,20,7]
我们知道preorder[0]
就是二分搜索树的root
,而且在inorder
中3
的左边是左子树,而3
的右边是右子树。接着用同样的方法找到左右子树的root
即可。
class Solution:
def buildTree(self, preorder, inorder):
"""
:type preorder: List[int]
:type inorder: List[int]
:rtype: TreeNode
"""
return self._buildTree(0, len(preorder)-1, 0, len(inorder)-1, preorder, inorder)
def _buildTree(self, pre_start, pre_end, in_start, in_end, preorder, inorder):
if pre_start > pre_end or in_start > in_end:
return
root = TreeNode(preorder[pre_start])
ini, i = 0, in_start
while i <= in_end:
if inorder[i] == root.val:
ini = i
i += 1
root.left = self._buildTree(pre_start+1, pre_end, in_start, ini-1, preorder, inorder)
root.right = self._buildTree(pre_start+ini-in_start+1, pre_end, ini+1, in_end, preorder, inorder)
return root
实际上上面这种写法非常臃肿,我们有更为简洁的写法。
class Solution:
def buildTree(self, preorder, inorder):
"""
:type preorder: List[int]
:type inorder: List[int]
:rtype: TreeNode
"""
if inorder:
ind = inorder.index(preorder.pop(0))
root = TreeNode(inorder[ind])
root.left = self.buildTree(preorder, inorder[0:ind])
root.right = self.buildTree(preorder, inorder[ind+1:])
return root
思路和第一种写法是一样的,关键在于寻找根节点。
同样对于递归可以解决的问题,我们都希望可以通过迭代去解决。对于迭代的关键还是在于找根节点。我们通过preorder
知道3
是整棵树的根节点,所以我们建立一个stack
,然后将3
加入到stack
中。栈顶是我们每次要考虑的根节点,我们每次遍历preorder
中的元素。我们首先考虑9
应该放在哪?通过preorder
我们知道9
一定是root左子树
的根节点,所以我们将9
加入到root(3).left
。
stack: 3 9
3
/
9
我们接着判断9
的左右孩子是谁?我们通过inorder
发现9
没有左右孩子,我们将9
出栈。
stack: 3
3
/
9
我们接着考虑20
应该放在哪。我们发现3
的右边是空的,所以我们将20
放到3
的右边(通过preorder
知道20
一定是右孩子的根)。
stack: 3 20
3
/ \
9 20
我们接着考虑15
应该放在哪。我们将15
加入到20
的左孩子(通过preorder
),同时入栈。
stack: 3 20 15
3
/ \
9 20
/
15
通过inorder
我们知道15
没有左右孩子,所以我们将15
出栈。
stack: 3 20 15
3
/ \
9 20
/
15
我们接着考虑7
应该放在哪。我们返现20
的右边是空,所以我们将7
放到20
的右边,同时将7
入栈。
stack: 3 20 7
3
/ \
9 20
/ \
15 7
接着就是具体实现上的细节。
class Solution:
def buildTree(self, preorder, inorder):
"""
:type preorder: List[int]
:type inorder: List[int]
:rtype: TreeNode
"""
if not inorder or not preorder:
return
root = TreeNode(preorder[0])
stack = [root]
i = 0
for node in preorder[1:]:
parent = stack[-1]
if parent.val != inorder[i]:
parent.left = TreeNode(node)
stack.append(parent.left)
else:
while stack and stack[-1].val == inorder[i]:
parent = stack.pop()
i += 1
parent.right = TreeNode(node)
stack.append(parent.right)
return root
reference:
https://articles.leetcode.com/construct-binary-tree-from-inorder-and-preorder-postorder-traversal/
我将该问题的其他语言版本添加到了我的GitHub Leetcode
如有问题,希望大家指出!!!