一棵二叉搜索樹可被遞歸地定義爲具有下列性質的二叉樹:對於任一結點,
其左子樹中所有結點的鍵值小於該結點的鍵值;
其右子樹中所有結點的鍵值大於等於該結點的鍵值;
其左右子樹都是二叉搜索樹。
所謂二叉搜索樹的“鏡像”,即將所有結點的左右子樹對換位置後所得到的樹。
給定一個整數鍵值序列,現請你編寫程序,判斷這是否是對一棵二叉搜索樹或其鏡像進行前序遍歷的結果。
輸入格式:
輸入的第一行給出正整數 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
—> 參考博客地址
前序遍歷:根結點 —> 左子樹 —> 右子樹
中序遍歷:左子樹—> 根結點 —> 右子樹
後序遍歷:左子樹 —> 右子樹 —> 根結點
分析:假設它是二叉搜索樹,一開始flag爲false,根據二叉搜索樹的性質將已知的前序轉換爲後序,轉換過程中,如果發現最後輸出的後序數組長度不爲n,那就設flag爲true(因爲還有可能是鏡面二叉搜索樹),然後清空後序數組,重新再轉換一次(根據鏡面二叉搜索樹的性質),如果依舊轉換後數組大小不等於n,就輸出NO否則輸出YES
#include <bits/stdc++.h>
using namespace std;
int n,arr[1010];
bool flag = false;
vector<int> res;
void helper(int down,int tail){
if(down > tail) return;
int left = down+1;
int right = tail;
if(!flag){
while(left <= tail && arr[left] < arr[down]) left++;
while(right > down && arr[right] >= arr[down]) right--;
}
else{
while(left <= tail && arr[left] >= arr[down]) left++;
while(right > down && arr[right] < arr[down]) right--;
}
if(left - right != 1) return ;
helper(down+1,right);
helper(left,tail);
res.push_back(arr[down]);
}
int main(){
cin>>n;
for(int i = 0;i < n;i++){
cin>>arr[i];
}
helper(0,n-1);
if(res.size() != n){
res.clear();
flag = true;
helper(0,n-1);
}
if(res.size() == n){
cout<<"YES"<<endl;
cout<<res[0];
for(int i = 1;i < res.size();i++){
cout<<" "<<res[i];
}
}else{
cout<<"NO";
}
return 0;
}