vlambda博客
学习文章列表

剑指系列S7 重建二叉树





剑指系列S7 重建二叉树
剑指系列S7 重建二叉树

题目描述



剑指系列S7 重建二叉树

给出一个二叉树,前序遍历和中序遍历的结果,并且两个遍历结果中均不含重复数字,将这个二叉树还原。

剑指系列S7 重建二叉树






剑指系列S7 重建二叉树
剑指系列S7 重建二叉树

简单分析




剑指系列S7 重建二叉树

首先必须知道前序遍历和中序遍历的是如何操作的。

前序遍历:根节点在前面,遍历后的结果顺序为

根节点 --> 左子树 --> 右子树

中序遍历:根节点在中间,遍历后的结果顺序为

左子树 --> 根节点 --> 右子树



然后我们根据前序遍历的结果,可以得到一个信息,前序遍历的第一个元素一定是root节点。知道root节点后,去中序遍历中找到该节点,以该节点为分界,左面就是左子树,右面就是右子树。这样就初步构建出了一颗二叉树,然后分别像上面流程一样递归处理左右子树就可以了。



前序遍历:[3,9,20,15,7] 

中序遍历:[9,3,15,20,7] 

其中前序中找到,root节点为3;

以[3]为分界,将中序遍历分为两部分:左子树[9]、右子树[15,20,7]

剑指系列S7 重建二叉树





剑指系列S7 重建二叉树
剑指系列S7 重建二叉树

Code



剑指系列S7 重建二叉树

这里递归的两个参数一个是前序遍历,一个是中序遍历。

当在中序遍历中找到左子树和右子树之后,如何确定他们对应的前序遍历是什么呢?

我们可以根据长度来判断,在中序找到根节点的位置k;

1、左子树的中序则是inorder[: k](这里的另一个信息是左子树的长度为k);

2、右子树的中序则是inorder[k + 1: ];

3、左子树的前序从下标1开始(左子树的下标0为根节点),一直到左子树的长度k,既preorder[1: k + 1];

4、右子树的前序既总前序序列剩下的部分preorder[k + 1: ];

剑指系列S7 重建二叉树


# 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 not preorder: return None root = TreeNode(preorder[0])        # 从中序遍历中找到根节点的位置 k = inorder.index(preorder[0]) # 递归左右子树 root.left = self.buildTree(preorder[1: k + 1], inorder[:k]) root.right = self.buildTree(preorder[k + 1:], inorder[k + 1:]) return root


在上面的代码中我们可以发现,每次递归的时候找根节点位置(既第13行)的时候时间复杂度是O(n)的,那么这里如果预处理一下,先建立一个中序序列中元素和下标的映射,则可以在O(1)复杂度下找到根节点在中序中的位置。(这里可以这样做的关键原因是题目中有说明两个遍历的序列中均不含重复数字)


递归时候传入的参数为四个边界前序左边界pl、前序右边界pr、中序左边界il,中序右边界ir。



1、左子树的序是[pl + 1, pl + k](其中k为根节点);

2、右子树的序是[pl + k + 1, pr];

3、左子树的序是[il, il + k - 1];

4、右子树的序是[il + k + 1, ir];



def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:    # 构建一下中序遍历中值与下标的映射 inorder_map = {v: i for i, v in enumerate(inorder)}    # 递归的参数传入四个边界,以长度为基准传入四个边界 def helper(pl, pr, il, ir): if pl > pr: return None root = TreeNode(preorder[pl]) k = inorder_map[preorder[pl]] - il root.left = helper(pl + 1, pl + k, il, il + k - 1) root.right = helper(pl + k + 1, pr, il + k + 1, ir) return root return helper(0, len(preorder) - 1, 0, len(inorder) - 1)