PAT 甲级 1043 Is It a Binary Search Tree (25 分) 递归建树

原题链接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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值