• 剑指 Offer 07. 重建二叉树重建二叉树


    • 题目描述

    输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

    例如,给出

    前序遍历 preorder = [3,9,20,15,7]
    中序遍历 inorder = [9,3,15,20,7]
    返回如下的二叉树:

    3
    /
    9 20
    /
    15 7
     

    限制:

    0 <= 节点个数 <= 5000

    • 分析

    首先我们需要了解下二叉树的前序遍历和中序遍历的特点

    前序遍历: 节点按照 [ 根节点 | 左子树 | 右子树 ] 排序,以题目示例为例:[ 3 | 9 | 20 15 7 ]

    中序遍历: 节点按照 [ 左子树 | 根节点 | 右子树 ] 排序,以题目示例为例:[ 9 | 3 | 15 20 7 ]

    那么可以得到:

    前序遍历的第一个元素即为root节点

    可根据这个root找到中序遍历中左子树和右子树的:[ 左子树 | 根节点 | 右子树 ]

    根据中序遍历的左右子树的节点数量,可将前序遍历划分为[ 根节点 | 左子树 | 右子树 ]

    根据子树特点,我们可以通过同样的方法对左(右)子树进行划分,每轮可确认三个节点的关系 。此递推性质让我们联想到用 递归方法 处理。

    参照题解:https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/solution/mian-shi-ti-07-zhong-jian-er-cha-shu-di-gui-fa-qin/

    此时需要理解的是:

                preorder_left:前序遍历的起始坐标
                preorder_right:前序遍历的终止坐标
                inorder_left:中序遍历的起始坐标
                inorder_right:中序遍历的终止坐标
    此时递归的左子树
    class Solution:
        '''
        哈希表+递归
        '''
        def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
            rootCan = {}
            if not preorder:
                return None
            for i in range(len(inorder)):
                rootCan[inorder[i]] = i
            
            def build(preorder_left, preorder_right, inorder_left, inorder_right):
                '''
                preorder_left:前序遍历的起始坐标
                preorder_right:前序遍历的终止坐标
                inorder_left:中序遍历的起始坐标
                inorder_right:中序遍历的终止坐标
                '''
                if preorder_left > preorder_right:
                    return None
                root = preorder[preorder_left] #前向遍历查找根节点
                root_inder_inorder = rootCan[root] #根节点在中序遍历中的索引
                order_num = root_inder_inorder - inorder_left #左子树长度
                node = TreeNode(root)
                #前序遍历中左子树的边界是[preorder_left + 1, preorder_left + order_num],中序遍历左子树的边界的[inorder_left, inorder_left + order_num - 1]
    #前序遍历中右子树的边界是[preorder_left + 1 + order_num, preorder_right],中序遍历右子树边界是[inorder_left + order_num + 1, inorder_right]
                node.left = build(preorder_left + 1, preorder_left + order_num, inorder_left, inorder_left + order_num - 1) #左子树 
    node.right
    = build(preorder_left + 1 + order_num, preorder_right, inorder_left + order_num + 1, inorder_right) #右子树

    return node
    root
    = build(0, len(preorder)-1, 0, len(preorder)-1)

    return root

    或者不用哈希表,就用数组递归:

    首先呢还是需要查找前序遍历的root节点在中序遍历中的位置,然后根据这个位置,可以前序遍历和中序遍历中的左右子树找出来。然后分别调用自身进行递归。

    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 len(preorder) == 0:#此时连根节点都没有 ,递归结束条件
                return None
            root = preorder[0]
            current_root= inorder.index(root)
            tree = TreeNode(root)
            #减小规模
            left_pre = preorder[1:current_root+1]
            right_pre = preorder[current_root+1:]
            left_in = inorder[:current_root]
            right_in = inorder[current_root+1:]
            tree.left = self.buildTree(left_pre, left_in) #调用自身
            tree.right = self.buildTree(right_pre, right_in)
            return tree
  • 相关阅读:
    单例模式(Singleton)的6种实现
    深入浅出单实例Singleton设计模式
    Singleton单例模式
    面试中的Singleton
    海量数据存储之Key-Value存储简介
    大数据时代的 9 大Key-Value存储数据库
    python 多线程两种实现方式,Python多线程下的_strptime问题,
    pycURL的内存问题
    百万级访问网站前期的技术准备
    IPv6 tutorial – Part 6: Site-local addresses and link-local addresses
  • 原文地址:https://www.cnblogs.com/yeshengCqupt/p/13435807.html
Copyright © 2020-2023  润新知