原题链接: 1043 Is It a Binary Search Tree (25 分)
题目大意:
BST:二叉搜索树。
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值
- 若它的右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值它的左、右子树也分别为二叉搜索树
现在,给定一个整数序列,请你判断它是否可能是某个二叉搜索树或其镜像进行前序遍历的结果。
分析:
首先,我们要知道一个BST的中序遍历一定是非递减的。
因为是否镜像只是会让它的前序遍历正反翻转,所以我们先读入它的前序遍历并且生成中序遍历并对中序遍历进行排序,然后正向建树,建树失败的话 将中序遍历翻转,重新反向建树建树;如果失败的话则输出NO
。
满分代码:
#include <iostream>
#include <set>
#include <map>
#include <vector>
#include <cmath>
#include <cstring>
#include <algorithm>
#define inf 0x3f3f3f3f
typedef long long LL;
using namespace std;
const int MAXN = 1e3+10;
/*
一个BST的中序遍历一定是非递减的
因为是否镜像只是会让它的前序遍历正反翻转,
所以我们先读入它的前序遍历并且生成中序遍历并对中序遍历进行排序,
正向建树,建树失败的话 将前序遍历翻转,重新建树
*/
int postOrder[MAXN], inOrder[MAXN], preOrder[MAXN];
int cnt, n;
// 利用前序遍历和中序遍历建树
bool build(int il, int ir, int pl, int pr, int type) {
// 遍历到了叶子结点的孩子时无法继续建树
if(il > ir) return true;
int root = preOrder[pl];
// k是一个用来找到root在inOrder中位置的指针
int k;
if(type == 0) {
// 通过for寻找root在中序中的位置 给k赋值
for(k = il; k <= ir; k++) {
if(inOrder[k] == root) {
break;
}
}
// 中序遍历中找不到root
if(k > ir) {
return false;
}
} else {
for(k = ir; k >= il; k--) {
if(inOrder[k] == root) {
break;
}
}
// 中序遍历中找不到root
if(k < il) {
return false;
}
}
bool res = true;
// 递归建左右子树
if(!build(il, k - 1, pl + 1, pl + 1 + (k - 1 - il), type)) {
res = false;
}
if(!build(k + 1, ir, pl + 1 + (k - 1 - il) + 1, pr, type)) {
res = false;
}
postOrder[cnt++] = root;
return res;
}
int main() {
cin >> n;
for(int i = 0; i < n; i++) {
cin >> preOrder[i];
inOrder[i] = preOrder[i];
}
sort(inOrder, inOrder + n);
// 正向建树
if(build(0, n-1, 0, n-1, 0)) {
puts("YES");
cout << postOrder[0];
for(int i = 1; i < n; i++) {
cout << " " << postOrder[i];
}
cout << endl;
} else {
// 翻转中序遍历 因为前序遍历是翻转且保持不变的
reverse(inOrder, inOrder + n);
// cnt是后序遍历的下标
cnt = 0;
if(build(0, n-1, 0, n-1, 1)) {
puts("YES");
cout << postOrder[0];
for(int i = 1; i < n; i++) {
cout << " " << postOrder[i];
}
cout << endl;
} else {
puts("NO");
}
}
return 0;
}