对于二叉搜索树,我们规定任一结点的左子树仅包含严格小于该结点的键值,而其右子树包含大于或等于该结点的键值。如果我们交换每个节点的左子树和右子树,得到的树叫做镜像二叉搜索树。
现在我们给出一个整数键值序列,请编写程序判断该序列是否为某棵二叉搜索树或某镜像二叉搜索树的前序遍历序列,如果是,则输出对应二叉树的后序遍历序列。
输入格式:
输入的第一行包含一个正整数N(≤1000),第二行包含N个整数,为给出的整数键值序列,数字间以空格分隔。
输出格式:
输出的第一行首先给出判断结果,如果输入的序列是某棵二叉搜索树或某镜像二叉搜索树的前序遍历序列,则输出YES
,否侧输出NO
。如果判断结果是YES
,下一行输出对应二叉树的后序遍历序列。数字间以空格分隔,但行尾不能有多余的空格。
输入样例1:
7
8 6 5 7 10 8 11
输出样例1:
YES
5 7 6 8 11 10 8
输入样例2:
7
8 6 8 5 10 9 11
输出样例2:
NO
解题思路
假设这是一颗二叉搜索树,前序遍历的顺序是根节点,左子树,右子树。大小顺序就是 root 小于root 大于等于root 。所以,对于下标为l到r的前序遍历序列,下标为l的点是其根节点,其后一串连续的且都比根节点小的是左子树的节点,之后直到r的一串大于等于根节点的都是其右子树的节点,若其中有小于根节点的,则说明这个序列不是二叉搜索树的前序遍历序列。按照这个顺序递归,即可遍历整棵树。题目要求后序遍历,即左子树, 右子树,根节点。那么在递归的时候先遍历左子树,再遍历右子树,然后把根节点的元素存入队列中,最后输出就是其后序遍历。
如果这是一颗镜像二叉搜索树,那么遍历的大小顺序应该是 root 大于等于root 小于root。思路和前面相似。改个符号就可以了。让每个序列分别跑着两种,如果两种都不是,则输出NO。否则为YES,并输出后序遍历。至于为什么要两种都跑,因为一个根节点肯只有左子树,或者只有右子树,这种情况就难以判断其到底是哪一种搜索树了。
代码如下
#include <iostream>
#include <queue>
using namespace std;
int num[1005];
queue<int> que;
bool dfs(int l, int r, bool flg) //1,根大小,0,根小大
{
if(l > r) //递归边界
return true;
int root = num[l];
if(flg){
for(int i = l + 1; i <= r; i ++){
if(num[i] < root){
for(int j = i + 1; j <= r; j ++){
if(num[j] >= root){
return false;
}
}
if(!dfs(l + 1, i - 1, flg)) //左子树
return false;
if(!dfs(i, r, flg)) //右子树
return false;
break;
}
if(i == r){
if(!dfs(l + 1, r, flg))
return false;
}
}
}
else {
for(int i = l + 1; i <= r; i ++){
if(num[i] >= root){
//cout << num[i] << endl; //
for(int j = i + 1; j <= r; j ++){
if(num[j] < root){
return false;
}
}
if(!dfs(l + 1, i - 1, flg)) //左子树
return false;
if(!dfs(i, r, flg)) //右子树
return false;
break;
}
if(i == r){
if(!dfs(l + 1, r, flg))
return false;
}
}
}
que.push(root); //存入根节点
return true;
}
void print() //输出后序遍历
{
cout << "YES" << endl;
bool first = true;
while(!que.empty()){
if(first)
first = false;
else
cout << " ";
int top = que.front();
que.pop();
cout << top;
}
cout << endl;
}
int main()
{
int n;
cin >> n;
for(int i = 1; i <= n; i ++)
cin >> num[i];
if(dfs(1, n, 1)){
print();
return 0;
}
else { //如果不是第一种,先把队列清空,然后跑第二种
while(!que.empty())
que.pop();
}
if(dfs(1, n, 0)){
print();
}
else //都不是输出NO
cout << "NO" << endl;
return 0;
}