105. 从前序与中序遍历序列构造二叉树;106. 从中序与后序遍历序列构造二叉树

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

思路蛮简单的:前序序列首元素是根节点,然后在中序序列中找该值,左侧为左子树,右侧为右子树,对两个子树递归调用即可。
一开始写的:

# Definition for a binary tree node.
# 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])
        index=inorder.index(preorder[0])
        root.left=self.buildTree(preorder[1:index+1],inorder[:index])
        root.right=self.buildTree(preorder[index+1:],inorder[index+1:])
        return root

花了大量时间在list的浅拷贝上,以及index()函数的过多使用。

官方题解的:
是用中序序列先做一个字典,然后每次查找根节点的index时就是O(1)的时间,以及递归函数参数中加上前后界,省去浅拷贝的时间。用了一个全局的变量,每次加一,即每次讲前序序列中第pre_idx 个数作为根,这个我想了半天,后来画了下递归过程,发现每次pre_idx 加一指示的正好是halper函数递归时要选取的根节点。。实在是有点取巧。。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def buildTree(self, preorder, inorder):
        """
        :type preorder: List[int]
        :type inorder: List[int]
        :rtype: TreeNode
        """
        def helper(in_left = 0, in_right = len(inorder)):
            nonlocal pre_idx
            # if there is no elements to construct subtrees
            if in_left == in_right:
                return None
            
            # pick up pre_idx element as a root
            root_val = preorder[pre_idx]
            root = TreeNode(root_val)

            # root splits inorder list
            # into left and right subtrees
            index = idx_map[root_val]

            # recursion 
            pre_idx += 1
            # build left subtree
            root.left = helper(in_left, index)
            # build right subtree
            root.right = helper(index + 1, in_right)
            return root
        
        # start from first preorder element
        pre_idx = 0
        # build a hashmap value -> its index
        idx_map = {val:idx for idx, val in enumerate(inorder)} 
        return helper()

时间、空间差距:
在这里插入图片描述

106. 从中序与后序遍历序列构造二叉树

思路和上题一样,后序的最后是根节点,还是去中序里去找该节点,再递归左右子树。

1.copy上题的官方题解,不过这里递归过程是从后序序列末尾依次向前选取,那么全局那个变量也要从最后开始依次递减,并且递归时要先递归右子树,再递归左子树。

class Solution:
    def buildTree(self, inorder, postorder):
        def func(le=0,ri=len(postorder)):
            nonlocal x
            if ri-le<1:
                return None
            _val=postorder[x]
            x-=1
            root=TreeNode(_val)
            index=dic.get(_val)
            root.right=func(index+1,ri) #半闭半开
            #这俩顺序不能反
            root.left=func(le,index)    #半闭半开
            return root
        x=len(postorder)-1
        dic={value:key for key,value in enumerate(inorder)}
        return func()

2.自己写的,四个参数,分别指示两个序列当前考察的两段子序列范围。时间、空间使用情况和上面的写法是基本一致,但好理解一些。
注意这里递归子树时左右的先后就无所谓了,因为当前考察的两段中序、后序子序列范围已经明确给出了,不需要为了什么奇怪的全局变量改动代码布局。。。

class Solution:
    def buildTree(self, inorder, postorder):
        def func(in_le,in_ri,po_le,po_ri):
            if in_ri-in_le<1:
                return None
            val=postorder[po_ri-1]
            root=TreeNode(val)
            index=dic.get(val)
            root.left=func(in_le,index,po_le,po_le+index-in_le)
            root.right=func(index+1,in_ri,po_le+index-in_le,po_ri-1)
            return root
        dic={value:key for key,value in enumerate(inorder)}
        return func(0,len(inorder),0,len(postorder))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值