這個題有一個非常詭異的地方。在一般的根據樹結構判斷是否爲二叉樹的問題中,這種情況:
是一定要特別注意的,如果用普通的dfs判斷左、右子樹是否小於、大於根節點,會把這顆樹誤判爲二叉搜索樹。
然而,如果僅給出一棵樹的前序序列,讓你判斷是否是二叉搜索樹,這種情況判爲正確也是沒問題的。因爲它的前序序列,43165,還可以表示爲下圖的樹:
這顆樹是二叉搜索樹。如果一個序列可以認爲是BST,也可以不是BST,那麼它就是BST···pta上的這一題是這麼ac的。
也因此 前序序列無法唯一表示一顆二叉樹(後序序列也不行。)
下面是由前序序列判斷是否爲BST的算法:
方法 isBST(int root,int tail)遞歸判斷一棵樹的左子樹是否都小於根節點,右子樹是否都大於根節點。
參數中的root表示爲當前樹的根節點,tail表示爲最後一個結點。
方法體中的i、j, 分別初始化爲根節點的下一個結點、當前樹的最後一個節點。經過操作後,如果當前樹是二叉排序樹,則i爲右子樹第一點,j爲左子樹最後一點。因此如果i!=j+1,則該樹不是二叉排序樹。
如果是的話,繼續進行左右子樹遍歷。
具體見代碼。
public class Main {
static int DLR[]=new int[1010];
static ArrayList<Integer> LRD=new ArrayList<Integer>();
static boolean isBST(int root,int tail) {//root爲當前樹根節點下表,tail爲當前樹最後一個節點下標
if(root>tail) {
return true;
}
int i=root+1;
int j=tail;
while(i<=tail&&DLR[i]<DLR[root]) {
i++;
}
while(j>root&&DLR[j]>=DLR[root]) {
j--;
}
if(j+1!=i) {
return false;
}
if(!isBST(root+1,j)) {
return false;
}
if(!isBST(i,tail)) {
return false;
}
LRD.add(DLR[root]);
return true;
}
static boolean reBST(int root,int tail) {
//基本同上一個方法
}
static PrintWriter out=new PrintWriter(System.out);
static void print() {
for(int i=0;i<LRD.size();i++) {
if(i!=0) {
out.print(" ");
}
out.print(LRD.get(i));
}
out.flush();
out.close();
}
public static void main(String args[]) {
InputReader sc=new InputReader(System.in);
int N=sc.nextInt();
for(int i=0;i<N;i++) {
DLR[i]=sc.nextInt();
}
if(isBST(0, N-1)) {
out.println("YES");
print();
}else {
LRD.clear();//清空鏈表的操作一定不要忘了!!
if(reBST(0, N-1)) {
out.println("YES");
print();
}else {
out.println("NO");
out.flush();
out.close();
}
}
}
}