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

39c12e6f17784f89ee9274a445179672.png

五一一师兄结婚

去给他当了伴郎

师兄家是在孝感的

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

吃饭得吃三天

等等等等

还是挺好玩的!

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

啊哈哈哈哈哈哈哈

579e17b80c5691a913ba2dd6a86a1e2b.png

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%以上。

01a6d09e8ddbe452e16f727166f1904d.png

2019/5/5 更新

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

程小新同学:动态规划方法心得​zhuanlan.zhihu.com
c5948b8a3ce9c971a40393b8b5652955.png

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

1b955316de48b3f26127a8569045d1da.png

代码如下:

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%左右。

d0079cd8b1c4216ab451b3d6f6b83a83.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值