![]() ![]() |
题目大意
给出一串二叉树的先序序列,判断是否为一棵二叉搜索树或其镜像树,如果是则输出“YES”,并输出它的后序序列;否则输出“NO”思路解析
对于二叉搜索树,其左子树均小于根节点,右子树均大于等于根节点。假设该树是一棵搜索二叉树,先序序列是由 (A)(序列B)(序列C) 三段构成的,其中A为根节点,则序列B中任意节点均小于A,序列C中任意节点均大于A。同样的道理,序列B和序列C也能找到类似的三段。而且最关键的,序列B的最后一个节点和序列C的第一个节点是相邻的,反之,如果不相邻则不是一棵二叉搜索树。
补注: 今天复习算法的时候看到此题,觉得实在不妥。虽然答案是正确的,但是要想在考场上做出来还是有难度的。
正如我在心经里的总结,见到BST就要想到中序遍历、从小到大、先序还原三个特点,这样才不至于乱了马脚,我认为这才是正规解法,原先的解法放在了本文的末尾,供大家平时研究。
毕竟考试时间有限,我们应该在最短的时间里AC,而不是陷入“代码洁癖”的怪圈。
示例代码(一)
#include<iostream>
#include<vector>
using namespace std;
struct node{
public:
int val;
struct node* left, *right;
};
node* insert(node* tree, int val) {
if (tree == NULL) {
tree = new node();
tree->val = val;
return tree;
}
if (val < tree->val)
tree->left = insert(tree->left, val);
else
tree->right = insert(tree->right, val);
return tree;
}
vector<int> res,post;
void preorder(node* tree) {
if (tree == NULL)return;
res.push_back(tree->val);
preorder(tree->left);
preorder(tree->right);
}
void postorder(node* tree) {
if (tree == NULL)return;
postorder(tree->left);
postorder(tree->right);
post.push_back(tree->val);
}
void rpreorder(node* tree) {//根右左
if (tree == NULL)return;
res.push_back(tree->val);
rpreorder(tree->right);
rpreorder(tree->left);
}
void rpostorder(node* tree) {//右左根
if (tree == NULL)return;
rpostorder(tree->right);
rpostorder(tree->left);
post.push_back(tree->val);
}
int main() {
int n, val;
scanf("%d", &n);
node* tree = NULL;
vector<int> vec;
for (int i = 0; i < n; i++) {
scanf("%d", &val);
vec.push_back(val);
tree = insert(tree, val);
}
preorder(tree);
int i = 0;
for (i; i < n && vec[i] == res[i]; i++);
if (i == n) {
postorder(tree);
printf("YES\n%d", post[0]);
for (int i = 1; i < n; i++)
printf(" %d", post[i]);
}
else {
res.clear();
rpreorder(tree);
i = 0;
for (i; i < n && vec[i] == res[i]; i++);
if (i == n) {
rpostorder(tree);
printf("YES\n%d", post[0]);
for (int i = 1; i < n; i++)
printf(" %d", post[i]);
}
else
printf("NO\n");
}
return 0;
}
示例代码(二)
#include<iostream>
#include<vector>
using namespace std;
int vec[1000];
vector<int> post;
bool isMirror = false;
void getPost(int root, int tail) {//给定先序序列首位位置,统计BST的后序序列
if (root > tail)return;
int i = root + 1,j = tail;
if (!isMirror) {
for (i; i <= tail && vec[i] < vec[root]; i++);//找左子树的最后一个节点
for (j; j > root && vec[j] >= vec[root]; j--);//找右子树的根
}
else {
for (i; i <= tail && vec[i] >= vec[root]; i++);//找左子树的最后一个节点
for (j; j > root && vec[j] < vec[root]; j--);//找右子树的根
}
if (j - i != -1) {//因为到最后会交错一位所以是j-i而不是i-j
return;
}
getPost(root+1, j);//遍历左子树
getPost(i, tail);//遍历右子树
post.push_back(vec[root]);//最后根节点入队
}
int main() {
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%d", &vec[i]);
getPost(0, n - 1);
if (post.size() != n) {
post.clear();
isMirror = true;
getPost(0, n - 1);
}
if (post.size() == n) {
printf("YES\n%d",post[0]);
for (int i = 1; i < n; i++) {
printf(" %d", post[i]);
}
}
else
printf("NO");
return 0;
}