python数据结构剑指offer-重建二叉树

例题

描述
给定节点数为 n 的二叉树的前序遍历和中序遍历结果,请重建出该二叉树并返回它的头结点。
例如输入前序遍历序列{1,2,4,5,3,6,7}和中序遍历序列{4,2,5,1,6,3,7},则重建出如下图所示。
python数据结构剑指offer-重建二叉树_第1张图片

解决思路

python数据结构剑指offer-重建二叉树_第2张图片
因为先序遍历根中序遍历是保存在数组中的,所以我们需要利用数组的性质,而不是上来就利用二叉树的性质,刚开始我是按照二叉树来做的,直到我失败了无数次之后,看到了函数的传入值是两个list,我好像参悟了什么,又好像没参悟透,然后我就看大佬的代码,看了好多次,手动运行了好多次,始终一知半解,好像懂了,又没懂,然后我就去看了评论区,发现大多数人和我一样,都刚开始没看懂,我才知道,我不是一个人在战斗。然后一气之下不做了,直接玩游戏,刷视频,好好的睡了一觉,起来之后,一切豁然开朗,拿到代码顺序读明白了,现在把这题的思路写下来,帮助后来人。

利用二叉树的性质将数组分类

根据先序遍历,将根节点找到,是1
python数据结构剑指offer-重建二叉树_第3张图片
然后在根据中序遍历,找到左子树和右子树
python数据结构剑指offer-重建二叉树_第4张图片
这个时候根据左右子树,再将先序遍历划分为三部分
python数据结构剑指offer-重建二叉树_第5张图片
至此,二叉树已经处理完毕,现在在处理他的位置

利用数组的位置处理

先序遍历找位置

处理一棵二叉树,肯定要先进入根,所以我们先在先序遍历里面找到根以及根的位置
python数据结构剑指offer-重建二叉树_第6张图片
找到根之后,我们肯定要接着找根,先处理左子树,在处理右子树,那么我们这个时候在找到左子树的根
python数据结构剑指offer-重建二叉树_第7张图片
左子树的根找到了,我们现在先找右子树的根,先不去处理左子树,一会一起处理,因为处理他们的办法是相同的
python数据结构剑指offer-重建二叉树_第8张图片
会发现右子树的根的位置恰好是根节点+左子树的长度

中序遍历找位置

根据先序遍历,我们在中序遍历里面找一下位置
python数据结构剑指offer-重建二叉树_第9张图片
我们可以找到中序遍历中根的位置
因为我们在先序遍历里面已经确定了一下左右子树根的位置,这个时候我们只需要在中序遍历里面确定他们的长度即可
python数据结构剑指offer-重建二叉树_第10张图片
从这我们可以知道左子树的长度为3,根节点的位置,右子树的长度为3,那么我们根据数组的性质,是不是可以推导以下推论:

  1. 左子树长度+根长度 = 数组总长-右子树长度
  2. 左子树的边界=0 ~ root-1(因为数组是从0开始计数,所以正好是0-2)
  3. 右子树的边界=root+1 ~ 数组总长-1(因为数组的长度是按照数量来计算,但是数组是从0开始计数)

至此,我们总结一下,整理成一个表格
python数据结构剑指offer-重建二叉树_第11张图片
这个时候我们发现这样看得懂,但是如何系统化呢?
4. 根节点在先序遍历里面找
5. 长度在中序遍历里面找
得出这样两条解决,我们开始解决
python数据结构剑指offer-重建二叉树_第12张图片
从这里我们可以看出,左子树的左边界我们如果设成left,则右子树的根节点就为i-left+root+1:i-left为左子树的长度+根节点在先序遍历中的位置,这个时候仅仅是根节点根左子树的长度,在加1,就是右子树的根节点
python数据结构剑指offer-重建二叉树_第13张图片
这个时候我们完成了递归公式,但是递归有两要素,结束条件和递归公式,现在我们在找结束条件。
刚才我们是很多数据,这个时候我们采用分治的思想,看看只有两个节点的时候是什么情况
python数据结构剑指offer-重建二叉树_第14张图片
python数据结构剑指offer-重建二叉树_第15张图片
python数据结构剑指offer-重建二叉树_第16张图片
可以发现,当left>right的时候,象征这递归结束了,所以我们把left 至此,我们把重建二叉树的全流程结束了。

       def reConstructBinaryTree(self , pre: List[int], vin: List[int]) -> TreeNode:
        # write code here
        def cur(root,left,right):
            if left > right:
                return
            # 先在先序遍历拿到根节点
            preroot = pre[root]
            # 创建根节点,方便下面递归使用
            node = TreeNode(pre[root])
            # 在找到根节点的位置
            i = in_dic[preroot]
            # 根据之前得到的公式,开始遍历
            node.left = cur(root + 1,left,i-1)
            node.right = cur(i- left + root + 1,i+1,right)
            return node

        in_dic = {}
        # 哈希表使用中序遍历,这样好找I值
        for x,i in enumerate(vin):
            in_dic[i] = x

        return cur(0,0,len(vin)-1)

结论

做树做递归,可以先一步一步推导一下,推导了,也就有规律了,然后在运用分治法进行最小分治就可以解决

你可能感兴趣的:(python数据结构,数据结构,python,算法)