二叉搜尋樹的後序遍歷序列

2022-07-09 20:36:08 字數 2753 閱讀 9878

輸入乙個整數陣列,判斷該陣列是不是某二叉搜尋樹的後序遍歷結果。如果是則返回 true,否則返回 false。假設輸入的陣列的任意兩個數字都互不相同。

5

/ \2

6 / \

13

示例 1:

輸入: [1,6,3,2,5

]輸出:

false

示例 2:

輸入: [1,3,2,6,5

]輸出:

true

如果這題說的是判斷該陣列是不是某二叉樹的中序遍歷結果,那麼這道題就非常的簡單了,因為二叉樹搜尋樹的中序遍歷結果一定是有序的,我們只需要判斷陣列是否有序就行了,但這道題要判斷的是不是某二叉搜尋樹的後序遍歷結果,這樣就有點難辦了。

二叉搜尋樹的特點是左子樹的值《根節點《右子樹的值。而後續遍歷的順序是:左子節點→右子節點→根節點;

比如下面這棵二叉樹,他的後續遍歷是

我們知道後續遍歷的最後乙個數字一定是根節點,所以陣列中最後乙個數字9就是根節點,我們從前往後找到第乙個比9大的數字10,那麼10後面的[10,12](除了9)都是9的右子節點,10前面的[3,5,4]都是9的左子節點,後面的需要判斷一下,如果有小於9的,說明不是二叉搜尋樹,直接返回false。然後再以遞迴的方式判斷左右子樹。

再來看乙個,他的後續遍歷是[3,5,13,10,12,9]

我們來根據陣列拆分,第乙個比9大的後面都是9的右子節點[13,10,12]。然後再拆分這個陣列,12是根節點,第乙個比12大的後面都是12的右子節點[13,10],但我們看到10是比12小的,他不可能是12的右子節點,所以我們能確定這棵樹不是二叉搜尋樹。搞懂了上面的原理我們再來看下**。

public

boolean verifypostorder(int

postorder)

private

boolean helper(int postorder, int left, int

right)

//然後對左右子節點進行遞迴呼叫

return helper(postorder,left,mid-1)&&helper(postorder,mid,right-1);

}

我們先來畫乙個節點多一些的二叉搜尋樹,然後觀察一下他的規律

他的後續遍歷結果是

[3,6,5,9,8,11,13,12,10]

從前往後不好看,我們來從後往前看

[10,12,13,11,8,9,5,6,3]

如果你仔細觀察會發現乙個規律,就是挨著的兩個數如果arr[i]我們剛才看的是公升序的,再來看一下降序的(這裡的公升序和降序都是基於後續遍歷從後往前看的,也就是上面的陣列)。

如果arr[i]>arr[i+1],那麼arr[i+1]一定是arr[0]……arr[i]中某個節點的左子節點,並且這個值是大於arr[i+1]中最小的。我們來看一下上面的陣列,比如13,11是降序的,那麼11肯定是他前面某乙個節點的左子節點,並且這個值是大於11中最小的,我們看到12和13都是大於11的,但12最小,所以11就是12的左子節點。同理我們可以觀察到11和8是降序,8前面大於8中最小的是10,所以8就是10的左子節點。9和5是降序,6和3是降序,都遵守這個規律。

根據上面分析的過程,很容易想到使用棧來解決。遍歷陣列的所有元素,如果棧為空,就把當前元素壓棧。如果棧不為空,並且當前元素大於棧頂元素,說明是公升序的,那麼就說明當前元素是棧頂元素的右子節點,就把當前元素壓棧,如果一直公升序,就一直壓棧。當前元素小於棧頂元素,說明是倒序的,說明當前元素是某個節點的左子節點,我們目的是要找到這個左子節點的父節點,就讓棧頂元素出棧,直到棧為空或者棧頂元素小於當前值為止,其中最後乙個出棧的就是當前元素的父節點。我們來看下**

public

boolean verifypostorder1(int

postorder)

//只要遇到了某乙個左子節點,才會執行上面的**,才會更

//新parent的值,否則parent就是乙個非常大的值,也就

//是說如果一直沒有遇到左子節點,那麼右子節點可以非常大

if (cur > parent) return

false

;

//入棧

stack.add(cur);

}return

true

; }

上面**可能大家有點蒙的是if(cur>parent)這一行的判斷。二叉搜尋樹應該是左子節點小於根節點,右子節點大於根節點,但上面為什麼大於父節點的時候要返回false,注意這裡的parent是在什麼情況下賦的值,parent並不一定都是父節點的值,相對於遇到了左子節點的時候他是左子節點的父節點。如果是右子節點,parent就是他的某乙個祖先節點,並且這個右子節點是這個祖先節點的乙個左子樹的一部分,所以不能超過他,有點繞,慢慢體會。

這題第一種方式是最容易想到的,每次把陣列劈兩半,因為通過第乙個while迴圈,左邊的都是小於根節點的,然後再判斷右邊的是不是都大於根節點,然後左右兩邊再以同樣的方式計算……。第二種方式也能解決,但比較繞,相對來說不太好容易理解,但如果真的搞懂了,會豁然開朗,也會有很大的收穫。

二叉搜尋樹的後序遍歷序列

題目 輸入乙個整數陣列,判斷該陣列是不是某二叉搜尋樹的後序遍歷的結果。如果是返回true,否則返回false。假設輸入的陣列的任意兩個數字都不相同。解答 二叉搜尋樹後序遍歷最後訪問的是根節點,根據根節點將陣列分成兩部分,前面一部分即左子樹值小於根節點值,後面一部分即右子樹的值大於根節點 再遞迴的檢查...

二叉搜尋樹的後序遍歷序列

輸入乙個整數陣列,判斷該陣列是不是某二叉搜尋樹的後序遍歷的結果。如果是則輸出yes,否則輸出no。假設輸入的陣列的任意兩個數字都互不相同。include using namespace std bool verifysquenceofbst int sequence,int length int j...

二叉搜尋樹的後序遍歷序列

輸入乙個整數陣列,判斷該陣列是不是某二叉搜尋樹的後序遍歷的結果。如果是則輸出yes,否則輸出no。假設輸入的陣列的任意兩個數字都互不相同。class solution 在二叉搜尋樹中右子樹的結點大於根結點 int j i for j0 left verifysquenceofbst lefttree...