这道题目确实不简单,但是如果能想通 其实也很简单
搞清楚中序和后序
首先我们要明白中序 和 后序的区别 中序是 左中又 后序则是左右中
按照这个逻辑 我们可以知道 后序数组的后面都是父节点
int val = postorder.back();
auto *node = new TreeNode(val);
if(postorder.size()==1)return node;
切割中序
根据后序中的父节点 我们切割中序 得出了两个中序数组
这两个中序数组 对应了这个父节点的左子树 和 右子树
//切割中序数组
vector<int> inorderleft(inorder.begin(),it);
vector<int> inorderright(it+1,inorder.end());
其实这里很好简单的想到 问题是怎么去切割 后序 从而将后序分为两个部分
首先在我们切割中序后 我们首先需要弹出后序的最后一个 因为我们已经使用了他
postorder.resize(postorder.size()-1);
然后就是关键的一步
切割后序
我们观察到 中序后序 他们的开头都是左 这就意味着 我们剔除了最后一个父节点 切割中序
那么中序中的左子树尺寸不就是对应了后序的左子树尺寸吗
所以我们切割后序 按照 中序的尺寸大小直接切割就完事了
vector<int> postorderleft(postorder.begin(),postorder.begin()+(int)inorderleft.size());
vector<int> postorderright(postorder.begin()+(int)inorderleft.size(),postorder.end());
其实还有一部很重要 就是我们需要终止递归结束条件
我们选择递归到叶子节点选择return
完整代码
class Solution {
public:
TreeNode* createTree(vector<int>& inorder, vector<int>& postorder){
//结束递归条件
if(postorder.empty())return nullptr;
//从后序数组最后一个构建头节点
int val = postorder.back();
auto *node = new TreeNode(val);
if(postorder.size()==1)return node;
auto it = find(inorder.begin(),inorder.end(),val);
//切割中序数组
vector<int> inorderleft(inorder.begin(),it);
vector<int> inorderright(it+1,inorder.end());
//切割后序数组
postorder.resize(postorder.size()-1);
vector<int> postorderleft(postorder.begin(),postorder.begin()+(int)inorderleft.size());
vector<int> postorderright(postorder.begin()+(int)inorderleft.size(),postorder.end());
node->left = createTree(inorderleft,postorderleft);
node->right = createTree(inorderright,postorderright);
return node;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if (inorder.size() == 0 || postorder.size() == 0) return nullptr;
return createTree( inorder, postorder);
}
};
类似题目还有
https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/
一并附上代码很简单
class Solution {
public:
TreeNode* createTree(vector<int>& preorder, vector<int>& inorder){
//分析两种遍历方法的区别 中左右 左中右
if(preorder.size()==1)return new TreeNode(preorder.front());
if(inorder.empty() || preorder.empty()) return nullptr;
int val = preorder.front();
TreeNode *node = new TreeNode(val);
preorder.erase(preorder.begin());
//切割中序
auto it = find(inorder.begin(),inorder.end(),val);
vector<int> inorderleft(inorder.begin(),it);
vector<int> inorderright(it+1,inorder.end());
//切割前序
vector<int> preorderleft(preorder.begin(),preorder.begin()+(int)inorderleft.size());
vector<int> preorderright(preorder.begin()+(int)inorderleft.size(),preorder.end());
node->left= createTree(preorderleft,inorderleft);
node->right= createTree(preorderright,inorderright);
return node;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(inorder.empty() || preorder.empty()) return nullptr;
return createTree( preorder, inorder);
}
};