返回

解开 LeetCode #106 谜题:从中序与后序遍历序列构建二叉树

IOS

文章

SEO 关键词:

正文:

置身于算法世界的探索之旅中,我们终会与 LeetCode #106 不期而遇。这是一道经典的二叉树构建题,需要我们根据给定的中序和后序遍历序列来构建出对应的二叉树。二叉树,作为数据结构家族中的重要一员,其构建过程蕴藏着丰富的算法思想和技巧,值得我们深入剖析和学习。

算法概述

踏上破解 LeetCode #106 的征途,我们首先要从算法的整体框架入手,纵览全局,把握要点。算法的基本思路是:利用后序遍历序列中的最后一个元素作为根节点,然后根据中序遍历序列将整棵树划分为左右两部分,再分别递归地构建出左右子树。这样,我们就可以逐步还原出整棵二叉树的结构。

具体实现

接下来,我们将具体剖析算法的实现细节。首先,我们需要明确后序遍历序列中的最后一个元素便是根节点。然后,我们需要根据中序遍历序列将整棵树划分为左右两部分。其中,根节点左边的元素构成了左子树,根节点右边的元素构成了右子树。接下来,我们可以递归地构建出左右子树,并将其与根节点连接起来,最终得到完整的二叉树。

语言示例

为了便于理解,我们以 Python、Java 和 C++ 三种语言分别给出算法的具体实现。

Python

def build_tree(inorder, postorder):
  if not inorder or not postorder:
    return None

  root_val = postorder[-1]
  root = TreeNode(root_val)
  root_index = inorder.index(root_val)

  left_inorder = inorder[:root_index]
  right_inorder = inorder[root_index + 1:]

  left_postorder = postorder[:root_index]
  right_postorder = postorder[root_index:-1]

  root.left = build_tree(left_inorder, left_postorder)
  root.right = build_tree(right_inorder, right_postorder)

  return root

Java

public TreeNode buildTree(int[] inorder, int[] postorder) {
  if (inorder.length == 0 || postorder.length == 0) {
    return null;
  }

  int rootVal = postorder[postorder.length - 1];
  TreeNode root = new TreeNode(rootVal);

  int rootIndex = 0;
  for (int i = 0; i < inorder.length; i++) {
    if (inorder[i] == rootVal) {
      rootIndex = i;
      break;
    }
  }

  int[] leftInorder = Arrays.copyOfRange(inorder, 0, rootIndex);
  int[] rightInorder = Arrays.copyOfRange(inorder, rootIndex + 1, inorder.length);

  int[] leftPostorder = Arrays.copyOfRange(postorder, 0, rootIndex);
  int[] rightPostorder = Arrays.copyOfRange(postorder, rootIndex, postorder.length - 1);

  root.left = buildTree(leftInorder, leftPostorder);
  root.right = buildTree(rightInorder, rightPostorder);

  return root;
}

C++

TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
  if (inorder.empty() || postorder.empty()) {
    return nullptr;
  }

  int rootVal = postorder.back();
  TreeNode* root = new TreeNode(rootVal);

  int rootIndex = 0;
  for (int i = 0; i < inorder.size(); i++) {
    if (inorder[i] == rootVal) {
      rootIndex = i;
      break;
    }
  }

  vector<int> leftInorder(inorder.begin(), inorder.begin() + rootIndex);
  vector<int> rightInorder(inorder.begin() + rootIndex + 1, inorder.end());

  vector<int> leftPostorder(postorder.begin(), postorder.begin() + rootIndex);
  vector<int> rightPostorder(postorder.begin() + rootIndex, postorder.end() - 1);

  root->left = buildTree(leftInorder, leftPostorder);
  root->right = buildTree(rightInorder, rightPostorder);

  return root;
}

复杂度分析

最后,我们来分析一下算法的时间复杂度和空间复杂度。算法的时间复杂度为 O(n^2),其中 n 是二叉树的节点数。这是因为算法需要对中序遍历序列进行多次搜索,每次搜索的时间复杂度为 O(n)。算法的空间复杂度为 O(n),这是因为算法需要存储中序遍历序列和后序遍历序列,这两个序列的总长度为 2n。

结语

LeetCode #106 题看似复杂,但只要掌握了二叉树的构建技巧,就能轻松破解。希望本文能够帮助你深入理解算法的原理,并在未来的算法挑战中取得佳绩。