返回与给定先序遍历 preorder 相匹配的二叉搜索树(binary search tree)的根结点。
(回想一下,二叉搜索树是二叉树的一种,其每个节点都满足以下规则,对于 node.left 的任何后代,值总 < node.val,而 node.right 的任何后代,值总 > node.val。此外,先序遍历首先显示节点的值,然后遍历 node.left,接着遍历 node.right。)
示例:
输入:[8,5,1,7,10,12]
输出:[8,5,10,1,7,null,12]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/construct-binary-search-tree-from-preorder-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路1:可以先从先序序列中获得中序遍历序列(BST中序有序)参考这一题
但是这样的解法不是最优的,排序花费了O(NlogN)
时间,最优解法明天来填坑。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
unordered_map<int,int> Map;//存储了中序序列的索引以便快速找到中序序列中根节点的位置
TreeNode* bstFromPreorder(vector<int>& preorder) {
vector<int> inOrder(preorder.begin(),preorder.end());
sort(inOrder.begin(),inOrder.end());
return buildTree(preorder,inOrder);
}
TreeNode* buildTree(vector<int>& preorder,vector<int>& inOrder)
{
if(preorder.size()==0&&inOrder.size()==0)
return nullptr;
for(int i = 0;i<inOrder.size();i++)
{
Map[inOrder[i]] = i;
}
// 传入参数:前序,中序,前序序列根节点,中序序列左边界,中序序列右边界
return Construct(preorder,inOrder,0,0,inOrder.size()-1);
}
TreeNode* Construct(vector<int>& preorder,vector<int>& inorder,int pre_root,int in_left,int in_right)
{
//停止条件
if(in_left > in_right)
return nullptr;
TreeNode* root = new TreeNode(preorder[pre_root]);
//根节点在中序序列中的位置 用于划分左右子树的边界
int in_root = Map[preorder[pre_root]];
//左子树在前序遍历中的根节点在于 pre_root+1;左子树在中序中的边界[in_left,in_root -1]
root->left = Construct(preorder,inorder,pre_root+1,in_left,in_root-1);
//右子树在前序中的根节点在于 根节点+ 左子树长度+1
//右子树在中序中的边界[in_root+1,in_right]
root->right = Construct(preorder,inorder,pre_root+in_root-in_left+1,in_root+1,in_right);
return root;
}
};