目录
1、题目链接
相似题目:
2、题目
3、解法(针对无重复值,哈希表+递归)
前序:根节点、左子树、右子树
后序:左子树、右子树、根节点二叉树的根节点一定是前序遍历的第一个节点,也是后序遍历的最后一个节点。
接下来,我们需要确定二叉树的左子树范围和右子树范围。
首先,仅凭前序和后序,得不到唯一的二叉树。结果可能有多个。
没有中序遍历的情况下,无法区分哪些节点属于左子树,哪些属于右子树。
第二个元素我们默认他是左子树的根节点。
函数头-----找出重复子问题
深搜函数头:preorder前序数组,
root :根节点在前序的下标
left:根节点所在子树的左边界
right:根节点所在子树的右边界
TreeNode* dfs(const vector<int>& preorder, int root, int left, int right)
函数体---解决子问题
哈希表 hash,它存储了后序遍历中每个节点的位置。在函数的开头,我们可以找到任意节点在后序遍历中的位置。
- 如果 left >right ,说明范围为空,直接返回空节点。
- 否则,我们构造一个新的节点 node ,它的值为前序遍历中的第一个节点的值,也就是 preorder[root]。
- 如果 left 等于 right ,说明 root 没有左子树也没有右子树,直接返回 root。
- 否则,左子树的根节点的值为 preorder[ root + 1],我们在后序遍历中找到 preorder[ root + 1] 的位置,记为 pos_root。
- 那么左子树的节点个数 left_size = pos_root − left + 1,由此可知左子树后序遍历中的范围是 [left , pos_root ],右子树在后序遍历中的范围是 [pos_root + 1, right −1]。
- 知道了左右子树的范围,我们就可以递归地重建左右子树,然后将左右子树的根节点分别作为 node 的左右子节点。最后返回 node。
cppif (left > right) return NULL; TreeNode* node = new TreeNode(preorder[root]);//构建根节点 //非常重要!!!影响整个代码的通过 //root 没有左子树也没有右子树,直接返回 root。 if (left == right) return node; int pos_root = hash[preorder[root + 1]]; //左子树的root在后序的下标 int left_size = pos_root - left + 1; //左子树结点数(含root) int right_root = root + left_size + 1;//右子树根节点在前序中的下标 node->left = dfs(preorder, root+1, left, pos_root); node->right = dfs(preorder, right_root, pos_root + 1, right - 1);
4、代码
cpp
class Solution {
//仅仅依靠前序、后序,会有存在多个二叉树
public:
unordered_map<int, int> hash;
//root 在pre的下标
TreeNode* dfs(const vector<int>& preorder, int root, int left, int right)
{
if (left > right)
return NULL;
TreeNode* node = new TreeNode(preorder[root]);//构建根节点
//非常重要!!!影响整个代码的通过
//root 没有左子树也没有右子树,直接返回 root。
if (left == right)
return node;
int pos_root = hash[preorder[root + 1]]; //左子树的root在后序的下标
int left_size = pos_root - left + 1; //左子树结点数(含root)
int right_root = root + left_size + 1;//右子树根节点在前序中的下标
node->left = dfs(preorder, root+1, left, pos_root);
node->right = dfs(preorder, right_root, pos_root + 1, right - 1);
return node;
}
TreeNode* constructFromPrePost(vector<int>& preorder, vector<int>& postorder) {
//postorder填充hash
for (int i = 0; i < postorder.size(); i++)
{
hash[postorder[i]] = i;
}
return dfs(preorder, 0, 0, postorder.size() - 1);
}
};