题目链接:105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)
目录
题目描述:
方法一:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* build(vector<int>& preorder, vector<int>& inorder, unordered_map<int,int>& inorder_maps, int& preorder_rootindex, int left, int right)
{
if (left > right) return nullptr;
//在前序遍历序列中,找到当前区间中的根节点的val值,并构建根节点
int root_val = preorder[preorder_rootindex];
TreeNode* cur = new TreeNode(root_val);
//前序遍历序列中的下一个数字,即为新的区间中的根节点的val值
preorder_rootindex++;
//中序遍历序列中,根节点的左边即为它的左子树
int newright = inorder_maps[root_val] - 1;
cur->left = build(preorder, inorder, inorder_maps, preorder_rootindex, left, newright);
//中序遍历序列中,根节点的右边即为它的右子树
int newleft = inorder_maps[root_val] + 1;
cur->right = build(preorder, inorder, inorder_maps, preorder_rootindex, newleft, right);
return cur;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
int n = preorder.size();
unordered_map<int, int> inorder_maps; //记录中序遍历序列中,各个元素的位置
for (int i = 0; i < n; i++)
{
inorder_maps[inorder[i]] = i;
}
int preorder_rootindex = 0; //记录当前区间的根节点在前序遍历序列中的位置
int left = 0; //当前区间的左指针
int right = n - 1; //当前区间的右指针
return build(preorder, inorder, inorder_maps, preorder_rootindex, left, right);
}
};
跟【从后序与中序遍历序列构造二叉树】一题一样,今天终于能够自己条理清晰地写出来了。
方法二:
来自2022.8.11的我,发现以前写的太复杂了,变量名取的太长也不是件好事,实在懒得看,自己重新写个简洁点的吧。
大致思路就是先序序列的第一个数就是当前子树的根节点,然后在中序序列中找到这个根节点的下标k,于是在中序序列中位于k左边的就是左子树,位于k右边的就是右子树,于是用递归就可以完成。
class Solution {
public:
//i1是当前子树的根节点在先序序列中的下标,[i2, j2]是当前子树的所有节点在中序序列中的下标
TreeNode* build(vector<int>& preorder, vector<int>& inorder, int i1, int i2, int j2)
{
if(i2 > j2) return nullptr;
int key = preorder[i1];
TreeNode* tmp = new TreeNode(key);
if (i2 == j2) return tmp; //当前子树只有一个节点时可以直接返回
int k;
//找到当前子树的根节点在中序序列中的下标,以K为边界,左边的就是左子树,右边的就是右子树
for (k = i2; k <= j2; k++)
{
if (inorder[k] == key) break;
}
//i1+1是左子树的根节点在先序序列中的下标,[i2, k-1]是左子树的所有节点在中序序列中的下标
tmp->left = build(preorder, inorder, i1 + 1, i2, k - 1);
//k-i2是左子树的节点数量
//i1+k-i2+1就是右子树的根节点在先序序列中的下标,[k+1, j2]是右子树的所有节点在中序序列中的下标
tmp->right = build(preorder, inorder, i1 + k - i2 + 1, k + 1, j2);
return tmp;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
int n = preorder.size();
return build(preorder, inorder, 0, 0, n - 1);
}
};