106.construct-binary-tree-inorder-and-postorder-traversal 从中序与后序遍历序列构造二叉树
大致思路,首先找到后序遍历序列的最后一个数,二叉树的根节点(root
)就是这个值,然后在中序遍历序列里找到这个数所在的位置(假设索引为i
),i
左边的数,是根节点左子树的数值,i右边的数,是根节点的右子树,然后根据左子树和右子树的数量,划分后序遍历的序列,分别找出划分后的两个序列的根节点,然后再找出两个根节点再中序遍历的序列中的位置,再划分后序遍历序列,依次迭代。
最直接的版本
class Solution {
public:
TreeNode *buildTree(vector<int> &inorder, vector<int> &postorder) {
// TreeNode *node = new TreeNode;
return get_root(inorder, postorder);
}
TreeNode *get_root(vector<int> &inorder, vector<int> &postorder) {
if (postorder.size() == 0)
return nullptr;
TreeNode *root = new TreeNode(postorder[postorder.size() - 1]);
// root->val = postorder[postorder.size() - 1];
int i = 0;
while (i < inorder.size()) {
if (root->val == inorder[i])
break;
i++;
}
//中序遍历的左半部分
vector<int> l_inorder(inorder.begin(), inorder.begin() + i);
vector<int> r_inorder(inorder.begin() + i + 1, inorder.end());
vector<int> l_postorder(postorder.begin(), postorder.begin() + i);
vector<int> r_postorder(postorder.begin() + i, postorder.end() - 1);
root->left = get_root(l_inorder, l_postorder);
//中序遍历切出来的右半部分
root->right = get_root(r_inorder, r_postorder);
return root;
}
};
利用vector
索引来划分vector
,避免递归中创建vector
的优化后的版本,要注意postorder
的索引是根据长度来确定的。
class Solution {
private:
TreeNode *get_root(vector<int> &inorder, vector<int> &postorder, int in_l, int in_r, int p_l, int p_r) {
if (p_l >= p_r)
return nullptr;
TreeNode *root = new TreeNode(postorder[p_r - 1]);
int i = 0;
while (i < in_r) {
if (root->val == inorder[i])
break;
i++;
}
//注意这里p_r应该赋什么值,应该根据inorder与postorder长度相等而得出
root->left = get_root(inorder, postorder, in_l, i, p_l, p_l + i - in_l);
// 注意这里p_l的值根据长度确定,由p_r - 1减去长度得到
root->right = get_root(inorder, postorder, i + 1, in_r, p_r + i - in_r, p_r - 1);
return root;
}
public:
TreeNode *buildTree(vector<int> &inorder, vector<int> &postorder) {
return get_root(inorder, postorder, 0, inorder.size(), 0, postorder.size());
}
};