1 题意
给定一个整数键值序列,判断其是否是对一棵二叉搜索树或其镜像进行前序遍历的结果。
链接:link。
2 思路
尝试从根节点递归建立二叉搜索树或其镜像树。
在建立二叉搜索树的过程中,对于每个子树根节点,总是能在序列中找到一个分界点,使得左边小于根节点,而右边不小于根节点。在建树过程中,如果出现找不到 分界点,则说明建树不成功。
2.1 时间复杂度分析
建树的时间复杂度为 O ( n ) \mathcal{O}(n) O(n),后序遍历的时间复杂度为 O ( n ) \mathcal{O}(n) O(n),所以时间复杂度为 O ( n ) \mathcal{O}(n) O(n)。
2.2 实现
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
const int N=1e5+10;
struct Node{
int val;
Node *lchild,*rchild;
};
int pre[N];
vector<int> res;
bool build_ori_tree(Node* &root,int be,int en){
if(be>en){
root=NULL;
return true;
}
root=new Node;
root->val=pre[be];
int k=be+1;
while(k<=en&&pre[k]<pre[be]) k++;
for(int i=k;i<=en;i++) if(pre[i]<pre[be]) return false;
return build_ori_tree(root->lchild,be+1,k-1)&&build_ori_tree(root->rchild,k,en);
}
bool build_mir_tree(Node* &root,int be,int en){
if(be>en){
root=NULL;
return true;
}
root=new Node;
root->val=pre[be];
int k=be+1;
while(k<=en&&pre[k]>=pre[be]) k++;
for(int i=k;i<=en;i++) if(pre[i]>=pre[be]) return false;
return build_mir_tree(root->lchild,be+1,k-1)&&build_mir_tree(root->rchild,k,en);
}
void bac_search(Node* root){
if(root==NULL) return;
bac_search(root->lchild);
bac_search(root->rchild);
res.push_back(root->val);
}
int main(){
int n;cin>>n;
for(int i=0;i<n;i++) cin>>pre[i];
Node *ori_tree,*mir_tree;
bool flag_ori=build_ori_tree(ori_tree,0,n-1);
bool flag_mir=build_mir_tree(mir_tree,0,n-1);
if(flag_ori||flag_mir){
if(flag_ori) bac_search(ori_tree);
else bac_search(mir_tree);
cout<<"YES"<<endl;
for(int i=0;i<res.size()-1;i++) cout<<res[i]<<" ";
cout<<res[res.size()-1]<<endl;
}
else cout<<"NO"<<endl;
return 0;
}