题目详见https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/
解题关键点:
- 后序遍历的数组最后一个元素代表的即为根节点
- 在中序遍历的数组中找到根节点所在的下标,然后根据其将中序遍历的数组分成左右两部分,左边部分即左子树,右边部分为右子树
又添加了些注释的代码
class Solution {
int post_idx; //这里使用一个全局变量记录“当前”的节点所在的位置
unordered_map<int, int> idx_map; //这里的是使用中序遍历建立的哈希表,idx_map[val] = idx++
public:
// 这里返回指针,也就是我们构造的二叉树的根节点
// in_left&in_right中的in指的是inorder,也就是中序遍历的index
TreeNode* helper(int in_left, int in_right, vector<int>& inorder, vector<int>& postorder){
// 如果这里没有节点构造二叉树了,就结束
if (in_left > in_right) {
return nullptr;
}
// 选择 post_idx 位置的元素作为当前子树根节点
int root_val = postorder[post_idx]; //这里这个post_idx全局变量让人发懵,请见代码中的1234条目
TreeNode* root = new TreeNode(root_val);
// 根据 root 所在位置分成左右两棵子树
int index = idx_map[root_val];
// 下标减一
// 2.现在post_idx来到了根节点前的一个节点,但是此时后序遍历是按照:左-右-根的顺序进行的。
// 因此我们移动到根左边的结点的时候该节点实际上属于根节点的右子树。
post_idx--;
// 构造右子树
// 3.因此我们先构造右子树
root->right = helper(index + 1, in_right, inorder, postorder);
// 构造左子树
// 4.现在post_idx来到了根节点前去除所有右子树节点之后的第一个节点,后序遍历是按照:左-右-根的顺序进行的,此时我们跳过了根和右,因此进入左子树,注意这里左-右-根我们是从右向左处理的。
// 因此我们移动到根左边的结点的时候该节点实际上属于根节点的右子树。
root->left = helper(in_left, index - 1, inorder, postorder);
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
// 从后序遍历的最后一个元素开始
//1.最开始post_idx在postorder的结尾,
post_idx = (int)postorder.size() - 1;
// 建立(元素,下标)键值对的哈希表
int idx = 0;
for (auto& val : inorder) {
idx_map[val] = idx++;
}
return helper(0, (int)inorder.size() - 1, inorder, postorder);
}
};
如有错误 敬请指正