📜  门| GATE CS 2011 |问题28(1)

📅  最后修改于: 2023-12-03 14:58:19.588000             🧑  作者: Mango

门 | GATE CS 2011 |问题28

本题是GATE计算机科学2011年的一道题目,涉及程序设计。题目如下:

给定二叉树的先序遍历和中序遍历,重建该二叉树。

例如,若先序遍历为ABCDEF,中序遍历为CBDAFE,那么从先序遍历和中序遍历中可以得到如下的二叉树:

     A
    / \
   B   C
  / \   \
 D   E   F
解题思路

从先序遍历和中序遍历中可以很容易地得到一个根和其在中序遍历中的位置。在重建二叉树时,我们首先从先序遍历中获取根,然后在中序遍历中找到根所在的位置。可以发现,这个位置将中序遍历划分成两部分 —— 左子树和右子树。我们可以根据这个位置,将先序遍历对应的部分也划分成两部分,分别对左子树和右子树递归调用重建函数。

重点在于递归调用函数时传入的参数,具体来说,左子树的先序遍历对应:先序遍历数组的第一个元素到根在中序遍历中的位置减一;右子树的先序遍历对应:先序遍历数组的根在中序遍历中的位置加一到结尾;左子树的中序遍历对应:中序遍历数组的起始位置到根在中序遍历中的位置减一;右子树的中序遍历对应:中序遍历数组的根在中序遍历中的位置加一到结尾。

下面是该算法的Python实现:

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

def buildTree(preorder, inorder):
    if not preorder or not inorder:
        return None

    # 根据中序遍历获取根
    root_val = preorder.pop(0)
    root = TreeNode(root_val)

    # 获取根在中序遍历中的位置
    idx = inorder.index(root_val)

    # 递归重建左子树和右子树
    root.left = buildTree(preorder, inorder[:idx])
    root.right = buildTree(preorder, inorder[idx+1:])

    return root
时间复杂度

该算法的时间复杂度为$ O(n^2) $,其中n为二叉树的大小。具体来说,由于每次递归都需要在中序遍历中查找根的位置,所以总体时间复杂度为所有递归层的复杂度之和。每层递归需要处理n个元素(即二叉树的大小),每次查找根的位置需要$O(n)$的时间复杂度,所以总体时间复杂度为$O(n^2)$。