PTA跳转:原题链接
二叉查找树(BST),对于每棵子树而言,左子树任意结点都比根结点小,右子树任意结点都比根结点大。
题目大意:现给出一串数字序列,如果满足一棵BST的前序遍历或镜像BST的前序遍历,输出“Yes”,并输出后序遍历。否则输出“NO”即可。
(镜像BST指左子树任意结点都比根结点大,右子树任意结点都比根结点小。)(题目规定BST右子树结点可以等于根结点,即镜像BST左子树结点可以等于根结点)
#include <iostream>
#include <vector>
using namespace std;
bool isMirror = 0;
vector<int> pre, post;
void getpost(int root, int tail) { //根结点为root,最后一个结点为tail的树
if (root > tail)
return;
int i = root + 1, j = tail;
if (!isMirror) {
while(i <= tail && pre[root] > pre[i])
i++; //最后i指向root右子树的第一个结点
while(j > root && pre[root] <= pre[j])
j--; //最后j指向root左子树的最后一个结点
} else {
while(i <= tail && pre[root] <= pre[i])
i++;
while(j > root && pre[root] > pre[j])
j--;
}
if (i - j != 1) //不满足二叉查找树条件,只要这棵树的任意子树执行了一次,这棵树就不是二叉查找树
return;
getpost(root + 1, j); //根结点为root+1,最后一个结点为j的子树
getpost(i, tail); //根结点为i,最后一个结点为tail的子树
//这2棵子树结点加起来等于tail-root,比原来的树少了一个结点
post.push_back(pre[root]);
}
int main() {
int n;
cin >> n;
pre.resize(n);
for (int i = 0; i < n; i++)
cin >> pre[i];
getpost(0, n - 1);
if (post.size() != n) {
isMirror = true; //不是左子树小、右子树大的二叉树,考虑镜像
post.clear();
getpost(0, n - 1);
}
if (post.size() == n) {
cout << "YES" << endl << post[0];
for(int i = 1; i < n; i++)
cout << " " << post[i];
} else {
cout << "NO";
}
return 0;
}
运行结果:
7
8 6 5 7 10 8 11
YES
5 7 6 8 11 10 8
7
8 10 11 8 6 7 5
YES
11 8 10 7 5 6 8
7
8 6 8 5 10 9 11
NO
氷鸢鸢鸢
2020.7.18