https://leetcode.com/problems/verify-preorder-sequence-in-binary-search-tree/description/
image.png
因為是先序的BST,就是先中間,再小,再大。先根,再左節(jié)點,再右節(jié)點。所以最大的一定在最后面。而且還有一個性質(zhì),開始時頭結(jié)點的大小,可以把后面的分為個區(qū)間。前半?yún)^(qū)間都比頭小,后半?yún)^(qū)間都比頭大。如果分不出來則不是BST的PREORDER.
不斷遞歸用這個套路。
public boolean verifyPreorder(int[] preorder) {
return help(preorder,0,preorder.length-1);
}
private boolean help(int[] pre,int s,int e) {
if(s>=e) return true;
int j = s+1;
int mid = pre[s];
while(j<=e){
if(pre[j]>mid) break;
j++;
}
for(int i = j; i<=e ; i++){
if(pre[i]<mid) return false;
}
return help(pre,s+1,j-1) &&help(pre,j,e);
}
follow up:
你可以用迭代的方式,并且用O 1的空間來實現(xiàn)嗎?
首先說迭代,因為是遞歸改非遞歸,我們就想到棧。我們可以嘗試用單調(diào)棧的特性,如把小于的數(shù)不斷推入棧中,然后發(fā)現(xiàn)有一個數(shù)比棧頂大了,分析這個點在原圖的位置明白,這就代表一個SUBTREE的左邊全部遍歷完了,來到了右邊,這時我們就需要不斷從棧里POP,直到POP到一個位置,比右邊這個要大。那么我們就知道最后一個POP的必然是當前最小,之后再有出現(xiàn)比他小的,就說明不對了,依次類推。
public boolean verifyPreorder(int[] preorder) {
int min = Integer.MIN_VALUE;
Stack<Integer> st = new Stack<>();
for(int num : preorder){
if(num < min) return false;
while(!st.isEmpty() && num > st.peek()){
min = st.pop();
}
st.push(num);
}
return true;
}
下面再思考如何O1,那么肯定需要用原數(shù)組來模擬棧了,那么有些數(shù)用過后肯定就不要再用了。根據(jù)這個規(guī)律,我們需要一個指針,如果不斷遞減,指針后移。如果有大了,POP時指針前移。還需要另外一個指針只往后走每次拿沒用過的數(shù)。就OK了。
public boolean verifyPreorder(int[] preorder) {
int min = Integer.MIN_VALUE;
int stack = 0;
for(int num : preorder){
if(num < min) return false;
while(stack!=0 && num > preorder[stack-1]){
min = preorder[--stack];
}
preorder[stack++] = num;
}
return true;
}