1. 程式人生 > 其它 >2021天梯賽模擬L2-3這是二叉搜尋樹嗎?

2021天梯賽模擬L2-3這是二叉搜尋樹嗎?

一棵二叉搜尋樹可被遞迴地定義為具有下列性質的二叉樹:對於任一結點,

其左子樹中所有結點的鍵值小於該結點的鍵值;
其右子樹中所有結點的鍵值大於等於該結點的鍵值;
其左右子樹都是二叉搜尋樹。
所謂二叉搜尋樹的“映象”,即將所有結點的左右子樹對換位置後所得到的樹。

給定一個整數鍵值序列,現請你編寫程式,判斷這是否是對一棵二叉搜尋樹或其映象進行前序遍歷的結果。

輸入格式:

輸入的第一行給出正整數 N(≤1000)。隨後一行給出 N 個整數鍵值,其間以空格分隔。

輸出格式:

如果輸入序列是對一棵二叉搜尋樹或其映象進行前序遍歷的結果,則首先在一行中輸出 YES ,然後在下一行輸出該樹後序遍歷的結果。數字間有 1 個空格,一行的首尾不得有多餘空格。若答案是否,則輸出 NO。

輸入樣例 1:

7
8 6 5 7 10 8 11

輸出樣例 1:

YES
5 7 6 8 11 10 8

輸入樣例 2:

7
8 10 11 8 6 7 5

輸出樣例 2:

YES
11 8 10 7 5 6 8

輸入樣例 3:

7
8 6 8 5 10 9 11

輸出樣例 3:

NO

這道題的思路就是用遞迴的思想來進行後序遍歷輸出,先找左子樹,再找右子樹

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,pre[1010];
vector<int> post;
bool mirror=false;
void getpost(int root,int tail)
{
	if(root>tail) return ;
 	int i=root+1;
 	int j=tail;
 	int root_data=pre[root];
	if(!mirror) 
	{
		while(pre[i]<root_data&&i<=tail) i++;
		while(pre[j]>=root_data&&j>root) j--;
	}
	else//如果是映象,只要相反一下就行
	{
		while(pre[i]>=root_data&&i<=tail) i++;
		while(pre[j]<root_data&&j>root) j--;
	}
	if(i!=j+1) return ;
	getpost(root+1,j);//找左子樹 
	getpost(i,tail);//找右子樹 
	post.push_back(root_data);
	//cout<<root_data<<endl;
}
int main()
{
	cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>pre[i];
	}
	getpost(0,n-1);
	if(post.size()<n)//vector小於n說明可能是映象,也可能都不是,後面再判斷一次 
	{
		post.clear();
		mirror=true;
		getpost(0,n-1);
	}
	if(post.size()<n) cout<<"NO";//既不是二叉搜尋樹,也不是映象 
	else
	{
		cout<<"YES"<<endl; 
		cout<<post[0];
		for(int i=1;i<n;i++)
		{
			cout<<" "<<post[i];
		}	
	}
	return 0;
}