1043 Is It a Binary Search Tree

题目大意

给出一串二叉树的先序序列,判断是否为一棵二叉搜索树或其镜像树,如果是则输出“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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值