返回
解开 LeetCode #106 谜题:从中序与后序遍历序列构建二叉树
IOS
2023-11-19 02:13:18
文章
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 题看似复杂,但只要掌握了二叉树的构建技巧,就能轻松破解。希望本文能够帮助你深入理解算法的原理,并在未来的算法挑战中取得佳绩。