題目描述
輸入一個整數數組,判斷該數組是不是某二叉搜索樹的後序遍歷的結果。如果是則輸出Yes,否則輸出No。假設輸入的數組的任意兩個數字都互不相同。
題目分析:
二叉搜索樹相對於二叉樹來說,必須滿足根節點的所有左子樹元素都小於根節點,所有右子樹節點都大於跟節點,而對於後序遍歷來說,二叉樹後序遍歷最後一個元素爲根節點,所以我們可以採用以下思路:來進行求解遍歷數組,找到根節點的左子樹和右子樹,即找到分界點,因爲左子樹所有元素都小於根節點,所以通過遍歷可以找到第一個不滿足條件的值,這也就是右子樹的第一個節點;找到分界點後,繼續判斷右子樹的所有節點是否大於根節點,判斷後繼續進行遞歸。
遞歸實現:
可以不用看下面這段話,如果對於j的初始取值有疑問,可以看下面的解釋。
在這裏一定要注意j的出示取值,j = end,而不是j = start,如果是start測試case只有部分通過,接下來進行分析:例如對於 int[] sequence = {4,6,7,5};在第一次進行執行時,分界點爲i = 1,左樹{4,6,7,5}start = 0,end = 0進行遞歸,返回true,接着右樹{4,6,7,5} ,start = 1 , end = 2 ,也就是{6,7}進行遞歸, 剛開始 j = end 初始化爲j = end = 2,而在第一個for循環中,不滿足if條件,循環結束,此時j的值沒有發生改變,仍然爲2,所以在第二個for循環中,循環體只執行一次,也不滿足條件,不會返回false,但是,如果是 j = start,那麼在第二個循環體中,由於就= 1,循環體執行一次,比較sequence[1]與sequence[2],而sequence[1]<sequence[2],直接返回false。這種情況就是爲了避免左樹爲空,而右樹只剩2個元素時,判斷第一個元素和第二個元素,也就是根節點進行比較,而且在這裏比較的右樹和根節點,判斷出來肯定是滿足右樹大於根節點,在第二個for循環中直接返回false。
public boolean VerifySquenceOfBST(int [] sequence) {
if (sequence == null ||sequence.length == 0) {
return false;
}
return judge(sequence, 0, sequence.length - 1);
}
private boolean judge(int[] sequence, int start, int end) {
if (start >= end) {
return true;
}
//後序遍歷,數組最後一個元素爲根節點。
int j = end;
//找到右子樹節點第一個元素的下標i,也判斷了左樹元素小於根節點元素
for (int i = start; i <= end; i++) {
if (sequence[i] > sequence[end]) {
j = i;
break;
}
}
//判斷右子樹所有元素大於根節點元素
for (int i = j; i <= end; i++) {
if (sequence[i] < sequence[end])
return false;
}
return judge(sequence, start, j - 1) && judge(sequence, j, end-1);
}