![在这里插入图片描述](https://img-blog.csdnimg.cn/20210308145000572.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1NMX1dvcmxk,size_16,color_FFFFFF,t_70)
一、前序+中序
1.1 递归(哈希表优化)
class Solution {
private:
unordered_map<int, int> val2idx;
int preIdx = 0;
public:
TreeNode* traverse(vector<int>& preorder, vector<int>& inorder, int left, int right) {
if (left > right) return nullptr;
auto root = new TreeNode(preorder[preIdx]);
int mid = val2idx[ preorder[preIdx++] ];
root->left = traverse(preorder, inorder, left, mid - 1);
root->right = traverse(preorder, inorder, mid + 1, right);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
int index = 0;
for (auto& val : inorder) val2idx[val] = index++;
return traverse(preorder, inorder, 0, preorder.size() - 1);
}
};
二、后序+中序
2.1 递归(未优化)
class Solution {
public:
TreeNode* traverse(vector<int>& inorder, vector<int>& postorder, int left, int right) {
if (left > right) return nullptr;
auto root = new TreeNode(postorder.back());
int rootIndex;
for (int i=left;i <= right;i++)
if (inorder[i] == postorder.back()) {
rootIndex = i;
break;
}
postorder.pop_back();
root->right = traverse(inorder, postorder, rootIndex + 1, right);
root->left = traverse(inorder, postorder, left, rootIndex - 1);
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
return traverse(inorder, postorder, 0, inorder.size() - 1);
}
};
由于每次要重新在inorder中从left到right顺序搜索与根节点相同值的索引,因此,对于海量数据的中序inorder向量,查值效率不是最高。
2.2 递归(哈希表优化)
对于海量数据的中序向量inorder,每次从left到right一个个检索与后序最后一个值是否相同,效率有些低。为了加速检索,可以空间换时间,即引入加速检索的哈希表数据结构,具体代码如下
class Solution {
private:
unordered_map<int, int> val2idx; // 存储中序数组的哈希表
int postIdx = 0;
public:
TreeNode* traverse(vector<int>& inorder, vector<int>& postorder, int left, int right) {
if (left > right) return nullptr;
auto root = new TreeNode( postorder[postIdx] );
// 通过哈希表快速获取根节点在中序inorder中的索引
int mid = val2idx[ postorder[postIdx--] ];
root->right = traverse(inorder, postorder, mid + 1, right);
root->left = traverse(inorder, postorder, left, mid - 1);
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
int index = 0;
// 注意:后序的根节点一定是从后往前
postIdx = inorder.size() - 1;
// 将中序数组按<val, index>存储到哈希表中
for (auto& val : inorder) val2idx[val] = index++;
return traverse(inorder, postorder, 0, inorder.size() - 1);
}
};
三、前序+后序
【思路】:不同于前中和后中,前后先通过前序最左节点,找到根节点,而前序根节点的右邻居是根节点的左子树,只是不知道左子树区间是多少,因此需要根据根节点左子树定位后序中的相同左子根节点,这样后序中根节点的左侧即为左子树区间,右侧至尾节点左邻居为右子树
- pre左子树区间:
[preleft + 1, preleft + 1 + mid - postleft]
- pre右子树区间:
[postleft, mid]
- post左子树区间:
[preleft + 2 + mid - postleft, preright]
- post右子树区间:
[mid + 1, postright - 1]
3.1 递归(哈希表优化)
class Solution {
private:
unordered_map<int, int> val2idx;
public:
TreeNode* traverse(vector<int>& pre, vector<int>& post, int preleft, int preright, int postleft, int postright) {
if (preleft > preright || postleft > postright) return nullptr;
auto root = new TreeNode(pre[preleft]);
if (preleft == preright) return root;
int mid = val2idx[ pre[preleft + 1] ];
// pre左子树区间:[preleft + 1, preleft + 1 + mid - postleft]
// pre右子树区间:[postleft, mid]
// post左子树区间:[preleft + 2 + mid - postleft, preright]
// post右子树区间:[mid + 1, postright - 1]
root->left = traverse(pre, post, preleft + 1, preleft + 1 + mid - postleft, postleft, mid);
root->right = traverse(pre, post, preleft + 2 + mid - postleft, preright, mid + 1, postright - 1);
return root;
}
TreeNode* constructFromPrePost(vector<int>& pre, vector<int>& post) {
int index = 0;
for (auto& val : post) val2idx[val] = index++;
return traverse(pre, post, 0, pre.size() - 1, 0, post.size() - 1);
}
};