轉載:點擊打開鏈接
這裏沿用傳統二叉查找樹(BST)的概念:所有左子樹都小於根,右子樹都大於根。(不止是直接孩子,還有間接孩子!)
現在給出一個整數序列,要求判斷它是否是一棵二叉查找樹BST的後序遍歷結果。
如果去掉BST這個條件,我們一般是不能只根據後序遍歷結果來確定某一棵樹的。
有了BST這個條件後,我們可以這麼做:
定義如下遞歸函數頭:
1 |
int judge( int * arr, int
start, int end) |
(1)另root = end-1,則arr[root]爲從start開始,end結束的子樹的根(後序遍歷麼!)
(2)我們另i從start開始,一直++,直到碰到第一個arr[i]大於arr[root]的,那麼此時的i已經位於右子樹了。從start~i-1是左子樹。
(3)顯然從i~end-2是右子樹,我們檢查這段arr[j],如果有發現<arr[root]的,直接返回false。(右子樹必須都大於根!)
(4)遞歸檢查左子樹 judge(arr, start, i-1) 和右子樹 judge(arr, i, end-2)。如果某一個judge返回0,那麼返回0,兩個都1返回1。
(5)如果start==end時候,或者arr==NULL時(空樹也是BST的一種!),可以直接返回1。
好了,代碼如下:
package bst;
public class Main {
/**
*
* @param nums
* @param start
* 數組下標從0開始
* @param end
* 數組下標
* @return
*/
private static boolean judge(int[] nums, int start, int end) {
// 空數組或者只有一個元素的數組也是二叉查找樹,返回true
if (nums == null || start == end) {
return true;
} else {
int root = end; // 最後的元素肯定是bst的根
int i = start;
for (; i < root; i++) { // 後序遍歷的前部分是左子樹,都小於根
if (nums[i] > nums[root]) {
break;
}
}
int j = i;
for (; j < root; j++) { // 後續遍歷的後部分是右子樹,都大於根
if (nums[j] < nums[root]) {
return false;
}
}
boolean left = true; // 遞歸判斷左子樹
if (i > 0) {
left = judge(nums, start, i - 1);
}
boolean right = true; // 遞歸判斷右子樹
if (i < end) {
right = judge(nums, i, end - 1);
}
return left && right;
}
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] nums = { 5, 7, 6, 9, 11, 10, 8 };
boolean result = judge(nums, 0, nums.length - 1);
System.out.println(result);
}
}