输入:两个整数数组 inorder(中序遍历)和 postorder(后序遍历)
要求:根据这两个序列构造二叉树 inorder 和 postorder 均无重复元素
输出:构造出的二叉树的根节点
思路:这道题是“前序+中序”构造二叉树的姊妹题,逻辑几乎完全一致,只是“定位根节点”的视角变了。
我们继续用“人脑模拟”的思路来拆解:
-
定位根节点(找尾巴): 在 前序遍历 中,根节点在最前面;而在 后序遍历 中,根节点总是藏在序列的 最后面(尾部)。 拿到
postorder的最后一个元素,它就是当前的根。 -
划分势力范围(切中序): 拿着这个根节点的值,去 中序遍历 里查找它的位置。 同样,在中序序列中,根节点 左边 的所有元素属于 左子树,右边 的所有元素属于 右子树。
-
递归的传递: 利用中序遍历计算出的左子树长度,去 后序遍历 中切分出对应的部分。 注意后序的结构:
[ 左子树全部 | 右子树全部 | 根 ]。 我们把末尾的根去掉后,剩下的序列前len个就是左子树的后序,后面剩下的就是右子树的后序。
见LC.105 | 从前序与中序遍历序列构造二叉树 | 树 | 递归分治
复杂度:
时间复杂度:O(N^2)
空间复杂度:O(N^2)
class Solution {
public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
return tree(inorder, postorder);
}
TreeNode* tree(vector<int> in, vector<int> post) {
if (in.empty()) {
return nullptr;
}
TreeNode* tmp = new TreeNode(post[post.size() - 1]);
vector<int> postleft,inleft,postright,inright;
int i = 0;
for (; i < in.size(); i++) {
if (in[i] == post[post.size() - 1]) {
break;
}
inleft.push_back(in[i]);
}
i += 1;
for (; i < in.size(); i++) {
inright.push_back(in[i]);
}
int j = 0;
for (int k = 0; k < inleft.size(); k++) {
postleft.push_back(post[j++]);
}
for (int k = 0; k < inright.size(); k++) {
postright.push_back(post[j++]);
}
tmp->left = tree(inleft, postleft);
tmp->right = tree(inright, postright);
return tmp;
}
};
151

被折叠的 条评论
为什么被折叠?



