题目:
输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
示例:
Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]
思路:
前序遍历是根据{根、左、右}的顺序遍历的,那么每次第一个节点就是“根”。中序遍历是根据{左,根,右}的顺序遍历的,故如果从前序遍历中得到根节点,就可根据中序遍历得到该节点的左右子树!然后代表前序遍历和中序遍历的列表,就可刨除掉此时的根节点,划分为新的左右子树的前序遍历和中序遍历列表,对于左/右子树而言,前序遍历的第一个节点是该子树的“根”,中序遍历中“根”的左右仍可找到这个根的子树。因为有一个重复的过程,自然而然想到“递归”。
细节:
递归三要素:1.终止条件(什么时候停止重复)2.递归关系(什么时候重复)3.每层递归的参数和返回值(也就是一层函数要干什么事)
1.终止条件:对于列表不为空的情况,一般的终止条件为当列表元素只剩一个时(此时无论前序遍历还是中序遍历肯定也只有一个节点),不用再对它划分左右子树了-->遍历到了叶子节点-->停止该分支的递归
2.特殊情况:如果树为空,返回空
3.递归关系:每次找到根节点之后,依据中序遍历找其左右子树
4.参数和返回值:要干的事为前序遍历找根,中序遍历找左右子树,则参数当然为前序遍历和中序遍历的列表,返回值是根据代码提示,最后要得到TreeNode类型的返回值,也就是返回整棵树的根节点,那我们每次递归可以找到子树的根节点,这个根节点肯定又是更高一层的树的子节点,最后一直向上最终调用递归的函数会返回整棵树的根节点的。
5.其他细节:每次截取列表时的索引号不能弄错;因为一个子树的根节点是更高一层树的子节点,为了完成整棵树的构建,需要将左右子节点(子树的根节点)与根节点(更高一层树的根节点)相连接。
代码:
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
if not preorder or not inorder:
return
if len(preorder)==1 or len(inorder)==1:
return TreeNode(preorder[0])
root_val=preorder[0]
root=TreeNode(root_val)
root_index=inorder.index(root_val)
leftnode=self.buildTree(preorder[1:1+root_index],inorder[:root_index])
rightnode=self.buildTree(preorder[1+root_index::],inorder[root_index+1:])
root.left=leftnode
root.right=rightnode
return root