思路: 由于时具有单调性的先序遍历,当出现单调性的结束位置便是左子树 -> 右子树(或右子树 -> 左子树)的转换。参考博客
代码实现:
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N = 1e5+10;
int n, a[N], mirror;
vector<int> ans;
void dfs(int l, int r){ // 5 3 2 4 7 6 8
if(l>r) return;
int i = l+1, j = r;
if(mirror){
while(i <= r && a[i] >= a[l]) i++; // l为根节点,若为镜像, 则左子树每个节点都大于根节点
while(j > l && a[j] < a[l]) j--; // 右子树的每个节点都小于等于根节点
}
else{
while(i <= r && a[i] < a[l]) i++; // l为根节点, 若不是镜像, 则左子树的每个节点都小于根节点
while(j > l && a[j] >= a[l]) j--; // 右子树每个节点都大于等于根节点
}
if(i-1 != j) return; // 若为二叉搜索树, i一定在右子树的根节点处(即找到7), j一定在左子树的尾节点处(即找到4)
dfs(l+1, j); // 递归左子树 (5的左子树为3 2 4)
dfs(i, r); // 递归右子树 (5的右子树为7 6 8)
ans.push_back(a[l]); // 从最后一个节点开始存答案
}
signed main()
{
cin >> n;
for(int i = 1; i <= n; i ++){
cin >> a[i];
}
dfs(1, n); //判断其是否是搜索二叉树
if(ans.size()!=n){
mirror = 1;
ans.clear();
dfs(1, n); //判断其是否是镜像的搜索二叉树
}
if(ans.size()!=n) cout << "NO" << endl;
else{
cout << "YES" << endl;
for(int i = 0; i < n; i ++){ //输出存储的后序答案
cout << ans[i] << " \n"[i==n-1];
}
}
return 0;
}