【题解】【PAT甲】1043 Is It a Binary Search Tree(25分)(前序中序转后序)(两种解法)

27 篇文章 0 订阅

题目链接

 PTA | 程序设计类实验辅助教学平台

题目描述

A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties:

  • The left subtree of a node contains only nodes with keys less than the node's key.
  • The right subtree of a node contains only nodes with keys greater than or equal to the node's key.
  • Both the left and right subtrees must also be binary search trees.

If we swap the left and right subtrees of every node, then the resulting tree is called the Mirror Image of a BST.

Now given a sequence of integer keys, you are supposed to tell if it is the preorder traversal sequence of a BST or the mirror image of a BST.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (≤1000). Then N integer keys are given in the next line. All the numbers in a line are separated by a space.

Output Specification:

For each test case, first print in a line YES if the sequence is the preorder traversal sequence of a BST or the mirror image of a BST, or NO if not. Then if the answer is YES, print in the next line the postorder traversal sequence of that tree. All the numbers in a line must be separated by a space, and there must be no extra space at the end of the line.

Sample Input 1:

7
8 6 5 7 10 8 11

结尾无空行

Sample Output 1:

YES
5 7 6 8 11 10 8

结尾无空行

Sample Input 2:

7
8 10 11 8 6 7 5

结尾无空行

Sample Output 2:

YES
11 8 10 7 5 6 8

结尾无空行

Sample Input 3:

7
8 6 8 5 10 9 11

结尾无空行

Sample Output 3:

NO

题目大意

 确定一棵树为BST树,给出这个树的先序序列,判断这个先序序列是不是BST树或者BST镜像树的先序序列

如果是的话输出YES和后序序列

如果不是的话输出NO

解题思路

 两种解法

第一种解法

        根据给定的先序序列创建BST树,然后在遍历BST树和他的镜像树,看遍历出来的先序序列和初始给的序列是不是相等,如果相等的话就说明YES,不相等的话就输出NO

第二种解法

        根据二叉搜索树的性质:

                1.一棵二叉搜索树的左子树一定小于根节点,右子树一定大于根节点

                2.推论,一棵二叉树左子树的最大值一定小于根节点,右子树的最小值一定大于根节点

                3.在先序遍历中,满足:根节点,左子树,右子树的遍历方法,所以左子树的最大值是左子树最后遍历的数值,右子树的最小值是右子树第一个遍历的数值,所以左子树的最大值和右子树的最小值的下标应该是紧挨着相差1的

                4.如果一棵树是平衡二叉树,那么他每一个子树的先序遍历的序列,从左到右第一个比根节点大的值的下标和从右向左第一个比根节点小的值的下标的差为一

                5.这个条件为充要条件

        例如有BST树

        先序序列为 

10276381115

         根据上面的性质有

int i=root+1,j=tail;
while(i<=tail&&pre[i]<pre[root])	i++;
while(j>root&&pre[j]>=pre[root])	j--;

        找到的i,j对应为,相差为一

ji
10276381115

题解

 第一种解法

#include<bits/stdc++.h>
using namespace std;
struct Node{
	struct Node *left;
	struct Node *right;
	int data;
};
typedef Node *List;
List insert(List root,int data){
	if(root==NULL){
		root=new Node();
		root->left=NULL;
		root->right=NULL;
		root->data=data;
	}
	else if(data>=root->data){
		root->right = insert(root->right,data);
	}
	else{
		root->left = insert(root->left,data);
	}
	return root;
}
vector<int> v;
string s,r;
void dfs(List x){
	if(x==NULL)	return ;
	s+=to_string(x->data);
	dfs(x->left);
	dfs(x->right);
	v.push_back(x->data);
}
vector<int> v2;
void dfs2(List x){
	if(x==NULL)	return ;
	r+=to_string(x->data);
	dfs2(x->right);
	dfs2(x->left);
	v2.push_back(x->data);
	
}
int main(){
	int n;
	cin>>n;
	List root=NULL;
	List mroot=NULL;
	string t;
	for(int i=0;i<n;i++){
		int data;
		cin>>data;
		t+=to_string(data);
		root=insert(root,data);
	}
	int flag=0;
	s.clear();
	List root1=root;
	dfs(root1);
	if(s==t)	flag=1;
	r.clear();
	dfs2(root);
	if(r==t)	flag=2;
	if(flag==1){
		cout<<"YES"<<endl;
		for(int i=0;i<v.size();i++){
			if(i!=0)	cout<<" ";
			cout<<v[i];
		}
	}
	else if(flag==2){
		cout<<"YES"<<endl;
		for(int i=0;i<v2.size();i++){
			if(i!=0)	cout<<" ";
			cout<<v2[i];
		}
	}
	else{
		cout<<"NO";
	}
}

第二种解法

#include<bits/stdc++.h>
using namespace std;
int n;
bool f=false;
vector<int> pre;
vector<int> post;
void postOrder(int root,int tail){        //root为根节点,tail为最后一个节点
	if(root>tail)	return ;
	int i=root+1,j=tail;
	if(!f){        //BST树
		while(i<=tail&&pre[i]<pre[root])	i++;
		while(j>root&&pre[j]>=pre[root])	j--;
	}
	else{            //BST镜像树
		while(i<=tail&&pre[i]>=pre[root])	i++;
		while(j>root&&pre[j]<pre[root])		j--;
	}
	if(i-j!=1)	return ;            //当不满足BST树的条件时break;
	postOrder(root+1,j);
	postOrder(i,tail);
	post.push_back(pre[root]);
}
int main(){
	cin>>n;
	pre.resize(n);
	for(int i=0;i<n;i++){
		cin>>pre[i];
	}
	postOrder(0,n-1);
	if(post.size()!=n){        //当后序遍历的长度不等于树的所有节点个数的时候,说明不满足题意
		post.clear();
		f=true;                //找镜像的
		postOrder(0,n-1);
	}
	if(post.size()==n){
		cout<<"YES"<<endl;
		for(int i=0;i<post.size();i++){
			if(i!=0)	cout<<" ";
			cout<<post[i];
		}
	}else{
		cout<<"NO"<<endl;
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值