题目描述:
根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
解题思路:
由于前序遍历先访问二叉树的父节点,再访问其左子节点,而中序遍历先访问左子节点再访问父节点。根据这个特点,可知前序遍历数组的第一个元素为树根节点,而在中序遍历数组中,在树根节点前面的元素为该树根节点的左子树,后边的元素为该树根节点的右子树。左子树和右子树也可以用这种方法构造。并且应该优先构造左子树,因为前序遍历是先访问左子树再访问右子树,所以在构造的时候,也要这样才能保持构造的节点顺序和前序遍历得到的列表的元素顺序一致。因此,本题可采用递归的方法,不断的将之前的子树再划分成左子树和右子树。递归结束条件为右子树或者左子树为空。
程序:
class Solution:
def buildTree(self, preorder, inorder):
# 为了节省每次遍历列表时间,引入哈希表,存储列表每个元素的下标
idxMap = {}
for i in range(len(inorder)):
idxMap[inorder[i]] = i
return self.buildNode(preorder, inorder, 0, len(inorder), idxMap)
def buildNode(self, preorder, inorder, s, e, idxMap):
# 递归结束条件 子树为空
if not preorder or s > e:
return
# 从列表中取出每棵子树的根节点
rootVal = preorder.pop(0)
root = TreeNode(rootVal)
# 如果子树中只有一个元素,直接返回该节点,不再进行递归
# if s == e:
# return root
# 递归构造根节点的左右子节点
root.left = self.buildNode(preorder, inorder, s, idxMap[rootVal] - 1, idxMap)
root.right = self.buildNode(preorder, inorder, idxMap[rootVal] + 1, e, idxMap)
return root
106题目描述
根据一棵树的中序遍历与后序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
中序遍历 inorder = [9,3,15,20,7] 后序遍历 postorder = [9,15,7,20,3]
返回如下的二叉树:
3 / \ 9 20 / \ 15 7
106解题思路
本题提供的是后序遍历得到的数组和中序遍历得到的数组,与105不同的时,后序遍历的列表最后一位元素为根节点,因此,只要从后序遍历的列表的最后一位元素开始,将其作为根节点,为其构造右子树和左子树,再不断的将之前构造的树再将其划分为左子树和右子树,知道树中没有元素。值得注意的是,因为是根据后序遍历,根节点的前驱是右子树,因此要先构造其右子树再构造左子树。
程序
class Solution:
def buildTree(self, inorder,postorder):
# 为了节省每次遍历列表时间,引入哈希表,存储列表每个元素的下标
idxMap = {}
for i in range(len(inorder)):
idxMap[inorder[i]] = i
return self.buildNode( postorder, inorder, 0, len(inorder)-1, idxMap)
def buildNode(self, postorder, inorder, s, e, idxMap):
# 递归结束条件 子树为空
if not postorder or s > e:
return
# 从列表中取出每棵子树的根节点
rootVal = postorder.pop(-1)
root = TreeNode(rootVal)
# 如果子树中只有一个元素,直接返回该节点,不再进行递归
if s == e:
return root
# 递归构造根节点的左右子节点
root.right = self.buildNode(postorder, inorder, idxMap[rootVal] + 1, e, idxMap)
root.left = self.buildNode(postorder, inorder, s, idxMap[rootVal] - 1, idxMap)
return root