https://pintia.cn/problem-sets/994805046380707840/problems/994805070971912192
思路:先序遍历即根左右,假设对应的数组区间为
[
h
e
a
d
,
t
a
i
l
]
[head,tail]
[head,tail],那么依据二叉搜索树的性质,可以将其分为三部分:
1.
1.
1.根节点,即
a
[
h
e
a
d
]
a[head]
a[head];
2.
2.
2.左子树,
a
[
h
e
a
d
…
l
]
a[head…l]
a[head…l];
3.
3.
3.右子树,
a
[
r
…
t
a
i
l
]
a[r…tail]
a[r…tail]。且左子树的值均小于根节点,右子树的值均大于等于根节点(可能出现无左/右子树的情况,不过影响不大),那么判断
r
r
r是否等于
l
+
1
l+1
l+1即可(相等就进入左右子树递归判断)。
#include<bits/stdc++.h>
using namespace std;
using ptr=bool(*)(int,int);
const int maxn=1005;
int n;
int a[maxn];
vector<int> vec;
inline bool les(int a,int b)
{
return a<b;
}
inline bool notles(int a,int b)
{
return a>=b;
}
bool isBST(int head,int tail,ptr cmp)//[l,r]
{
if(head>tail)
return 1;
int l=head+1,r=tail;
while(l<=tail&&cmp(a[l],a[head]))
++l;
while(r>head&&!cmp(a[r],a[head]))
--r;
if(r+1!=l||!isBST(head+1,r,cmp)||!isBST(l,tail,cmp))
return 0;
vec.push_back(a[head]);
return 1;
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
if(isBST(0,n-1,les))
{
printf("YES\n%d",vec[0]);
for(int i=1;i<n;i++)
printf(" %d",vec[i]);
printf("\n");
return 0;
}
vec.clear();
if(isBST(0,n-1,notles))
{
printf("YES\n%d",vec[0]);
for(int i=1;i<n;i++)
printf(" %d",vec[i]);
printf("\n");
}
else
printf("NO\n");
return 0;
}