題目
輸入一個整數數組,判斷該數組是不是某二叉搜索樹的後序遍歷結果。如果是則返回 true
,否則返回 false
。假設輸入的數組的任意兩個數字都互不相同。
參考以下這顆二叉搜索樹:
5
/ \
2 6
/ \
1 3
示例 1:
輸入: [1,6,3,2,5]
輸出: false
示例 2:
輸入: [1,3,2,6,5]
輸出: true
提示:
數組長度 <= 1000
解題思路
二叉搜索樹的左子樹節點的值小於根節點,二叉搜索樹的右子樹節點的值大於根節點。所以可以根據二叉搜索樹的定義,通過遞歸,判斷所有子樹的正確性 (即其後序遍歷是否滿足二叉搜索樹的定義)。若所有子樹都正確,則此序列爲二叉搜索樹的後序遍歷。
算法步驟:
- 1)遞歸終止條件: 當 left>=right ,說明此子樹節點數量 ≤,無需判別正確性,因此直接返回 true;
- 2)找根節點,根節點爲序列的最後一個元素:root = postorder[right];
- 3)劃分出左右子樹:遍歷後序遍歷的 [left, right-1] 區間,尋找第一個大於根節點的位置,索引記爲 i 。此時,可劃分出左子樹區間 [left, i-1], 右子樹區間 [i, right-1],根節點索引 right。
- 4)判斷左右子樹是否爲二叉搜索樹:
- 4.1)左子樹區間 [left, i-1] 內的所有節點都應小於 postorder[right],而上一步劃分左右子樹時已經保證左子樹區間的正確性,因此只需要判斷右子樹區間即可。
- 4.2)右子樹區間 [i, right-1] 內的所有節點都應大於 postorder[right],逐個遍歷此區間,當遇到小於 postorder[right] 的節點則跳出,直接返回 false。
- 5)返回值:所有子樹都需正確纔可判定正確,因此使用“與邏輯符 &&” 連接。
代碼
class Solution {
public boolean verifyPostorder(int[] postorder) {
return isPoster(postorder, 0, postorder.length-1);
}
private boolean isPoster(int[] postorder, int left, int right){
if(left>=right){
return true;
}
// 根節點是數組的最後一個
int root = postorder[right];
// 二叉搜索樹的左子樹節點的值應該小於根節點
int i=left;
for(; i<right; i++){
if(postorder[i] > root){
break;
}
}
// 二叉搜索樹的右子樹節點的值應該大於根節點
int j = i;
for(; j<right; j++){
// 如果在右子樹出現小於根節點的值,直接返回false
if(postorder[j] < root){
return false;
}
}
// 判斷左子樹是否是二叉搜索樹
boolean isLeft = isPoster(postorder, left, i-1);
// 判斷右子樹是否是二叉搜索樹
boolean isRight = isPoster(postorder, i, right-1);
return isLeft && isRight;
}
}