- 题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/
9 20
/
15 7
限制:
0 <= 节点个数 <= 5000
- 分析
首先我们需要了解下二叉树的前序遍历和中序遍历的特点
前序遍历: 节点按照 [ 根节点 | 左子树 | 右子树 ]
排序,以题目示例为例:[ 3 | 9 | 20 15 7 ]
中序遍历: 节点按照 [ 左子树 | 根节点 | 右子树 ]
排序,以题目示例为例:[ 9 | 3 | 15 20 7 ]
那么可以得到:
前序遍历的第一个元素即为root节点
可根据这个root找到中序遍历中左子树和右子树的:[ 左子树 | 根节点 | 右子树 ]
根据中序遍历的左右子树的节点数量,可将前序遍历划分为[ 根节点 | 左子树 | 右子树 ]
根据子树特点,我们可以通过同样的方法对左(右)子树进行划分,每轮可确认三个节点的关系 。此递推性质让我们联想到用 递归方法 处理。
此时需要理解的是:
preorder_left:前序遍历的起始坐标 preorder_right:前序遍历的终止坐标 inorder_left:中序遍历的起始坐标 inorder_right:中序遍历的终止坐标
此时递归的左子树
class Solution: ''' 哈希表+递归 ''' def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode: rootCan = {} if not preorder: return None for i in range(len(inorder)): rootCan[inorder[i]] = i def build(preorder_left, preorder_right, inorder_left, inorder_right): ''' preorder_left:前序遍历的起始坐标 preorder_right:前序遍历的终止坐标 inorder_left:中序遍历的起始坐标 inorder_right:中序遍历的终止坐标 ''' if preorder_left > preorder_right: return None root = preorder[preorder_left] #前向遍历查找根节点 root_inder_inorder = rootCan[root] #根节点在中序遍历中的索引 order_num = root_inder_inorder - inorder_left #左子树长度 node = TreeNode(root) #前序遍历中左子树的边界是[preorder_left + 1, preorder_left + order_num],中序遍历左子树的边界的[inorder_left, inorder_left + order_num - 1]
#前序遍历中右子树的边界是[preorder_left + 1 + order_num, preorder_right],中序遍历右子树边界是[inorder_left + order_num + 1, inorder_right]
node.left = build(preorder_left + 1, preorder_left + order_num, inorder_left, inorder_left + order_num - 1) #左子树
node.right = build(preorder_left + 1 + order_num, preorder_right, inorder_left + order_num + 1, inorder_right) #右子树
return node
root = build(0, len(preorder)-1, 0, len(preorder)-1)
return root
或者不用哈希表,就用数组递归:
首先呢还是需要查找前序遍历的root节点在中序遍历中的位置,然后根据这个位置,可以前序遍历和中序遍历中的左右子树找出来。然后分别调用自身进行递归。
class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None class Solution: ''' 数组+递归法求解 ''' def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode: if len(preorder) == 0:#此时连根节点都没有 ,递归结束条件 return None root = preorder[0] current_root= inorder.index(root) tree = TreeNode(root) #减小规模 left_pre = preorder[1:current_root+1] right_pre = preorder[current_root+1:] left_in = inorder[:current_root] right_in = inorder[current_root+1:] tree.left = self.buildTree(left_pre, left_in) #调用自身 tree.right = self.buildTree(right_pre, right_in) return tree