LeetCode105-从前序与中序遍历序列构造二叉树

五一一师兄结婚

去给他当了伴郎

师兄家是在孝感的

发现那边的习俗真的是和我老家不一样

吃饭得吃三天

等等等等

还是挺好玩的!

话不多说,直接上我和我朋友的合照

啊哈哈哈哈哈哈哈


105-从前序与中序遍历序列构造二叉树

根据一棵树的前序遍历与中序遍历构造二叉树。

注意:
你可以假设树中没有重复的元素。

例如,给出

前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]

返回如下的二叉树:

    3
   / \
  9  20
    /  \
   15   7

思路:

首先我们都知道先序遍历的递归定义是 根-左-右,中序遍历的定义为 左-中-右。

其实如果给你,前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = [9,3,15,20,7],大部分人能直接把这棵树徒手画出来,思路大致为:先序遍历的第一个节点是根节点,再找到它在中序遍历中的位置,那么左右子树就找到了,接着重复上述步骤直到结束。那么用代码该怎么表示呢。

所以我们先要有四个参数:l1,r1,l2,r2,[l1, r1]代表先序遍历序列,[l2, r2]代表后序遍历序列。而[l1]就是根节点,接着我们找到[l1]在[l2, r2]中的位置mid,lsize = mid - l2 就是左子树的长度,rsize = r2 - mid 就是右子树的长度。我们可以通过以上信息可以得到子树在先序和中序遍历中的“起止索引”,接着递归处理(其实也可以用栈来处理)

代码如下:

class TreeNode(object):
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

class Solution(object):
    def buildTree(self, preorder, inorder):
        """
        :type preorder: List[int]
        :type inorder: List[int]
        :rtype: TreeNode
        """
        if preorder is None or inorder is None:
            return None
        # 定义一链表用来记录中序序列中元素的下标值
        dict_in = {}
        for index, value in enumerate(inorder):
            dict_in[value] = index
        length = len(preorder)-1

        # 使用深度遍历方法遍历
        def dfs(pre_start, pre_end, in_start, in_end, preorder,inorder,dict_in):
            if pre_end >= pre_start and in_end >= in_start:
                root = TreeNode(preorder[pre_start])
                # 求得根节点的val值在中序序列中的下标值
                mid_index = dict_in[preorder[pre_start]]
                # 分别求得左、右子树的长度
                l_len = mid_index - in_start
                r_len = in_end - mid_index
                # 求得根节点root的左子树
                root.left = dfs(pre_start+1,pre_start+l_len,in_start,
                                in_start+l_len-1, preorder, inorder,dict_in)
                root.right = dfs(pre_start+l_len+1,pre_start+l_len+r_len,mid_index+1,
                                mid_index+r_len, preorder, inorder,dict_in) 
                return root
        return dfs(0, length, 0, length, preorder, inorder, dict_in)
            

if __name__ == "__main__":
    preorder = [3, 9, 20, 15, 7]
    inorder = [9, 3, 15, 20, 7]
    BTree = Solution().buildTree(preorder, inorder)
    print(BTree)

执行效率还是挺不错的,在90%以上。

 


2019/5/5 更新

上面那种方法的参数好像偏多,我估计很多人都晕乎了。突然get到一种参数很少的方法,想来分享一波。其实本题的核心算法还是动态规划方法,对这个算法思想还不熟悉的读者可以看看我之前写的一篇博文。

https://blog.csdn.net/weixin_36431280/article/details/86616672

于本题而言,就是不停找一个节点的左子树和右子树的问题,如下图所示:

代码如下:

class Solution(object):
    def buildTree(self, preorder, inorder):
        """
        :type preorder: List[int]
        :type inorder: List[int]
        :rtype: TreeNode
        """
        if len(preorder) == 0:
            return
        # 获得根节点在中序序列中的下标值
        mid_index = inorder.index(preorder[0])
        # 开始创建节点
        root = TreeNode(preorder[0])
        # preorder[1:mid_index+1], inorder[:mid_index] 对应着先序序列和中序序列的左子树的值
        root.left = self.buildTree(preorder[1:mid_index+1], inorder[:mid_index])
        # preorder[mid_index+1:], inorder[mid_index+1:] 对应着先序序列和中序序列的右子树的值
        root.right = self.buildTree(preorder[mid_index+1:], inorder[mid_index+1:])
        return root
            

if __name__ == "__main__":
    preorder = [3, 9, 20, 15, 7]
    inorder = [9, 3, 15, 20, 7]
    BTree = Solution().buildTree(preorder, inorder)
    print(BTree)

不过执行效率有些低,在50%左右。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学习的学习者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值