二叉搜尋樹定義:左子樹中所有節點的值 < 根節點的值;右子樹中所有節點的值 > 根節點的值;其左、右子樹也分別為二叉搜尋樹。
從定義出發:左子樹所有值小於根節點,右子樹所有值大於根節點。
根據二叉搜尋樹的定義,可以通過遞迴,判斷所有子樹的 正確性 (即其後序遍歷是否滿足二叉搜尋樹的定義) ,若所有子樹都正確,則此序列為二叉搜尋樹的後序遍歷。
終止條件: 當 i≥j ,說明此子樹節點數量 ≤ 1 ,無需判別正確性,因此直接返回 true;
遞推工作:
劃分左右子樹:
遍歷後序遍歷的 [i, j]區間元素,尋找 第乙個大於根節點 的節點,索引記為 m 。此時,可劃分出左子樹區間 [i,m−1] 、右子樹區間 [m, j - 1] 、根節點索引 j 。
判斷是否為二叉搜尋樹:
左子樹區間 [i,m−1] 內的所有節點都應 << postorder[j] 。而第 1.劃分左右子樹 步驟已經保證左子樹區間的正確性,因此只需要判斷右子樹區間即可。
右子樹區間 [m, j-1] 內的所有節點都應 >> postorder[j] 。實現方式為遍歷,當遇到 ≤postorder[j] 的節點則跳出;則可通過 p = j 判斷是否為二叉搜尋樹。
所有子樹都需正確才可判定正確,因此使用 與邏輯符 && 連線。
p=j : 判斷 此樹 是否正確。
recur(i,m−1) : 判斷 此樹的左子樹 是否正確。
recur(m,j−1) : 判斷 此樹的右子樹 是否正確。
class
solution
boolean
recur
(int
postorder,
int i,
int j)
}
從名字上就聽的出來,單調棧中存放的資料應該是有序的,所以單調棧也分為單調遞增棧和單調遞減棧
單調遞增棧:單調遞增棧就是從棧底到棧頂資料是從大到小,演算法思想:
棧內單調遞增,每次遇到stack.peek() > postorder[i]時就進行判斷輸出。
單調遞減棧:單調遞減棧就是從棧底到棧頂資料是從小到大,演算法思想:
棧內單調遞減,每次遇到stack.peek() < postorder[i]時就進行判斷輸出。
設後序遍歷倒序列表為 [rn,rn−1,...,r1],遍歷此列表,設索引為 i ,若為 二叉搜尋樹 ,則有:
當節點值ri>ri+1 時: 節點 ri一定是節點 ri+1的右子節點。
當節點值ri
初始化: 單調棧 stack ,父節點值 root = +∞ (初始值為正無窮大,可把樹的根節點看為此無窮大節點的左孩子);
倒序遍歷 postorder :記每個節點為 ri;
判斷: 若 ri>root ,說明此後序遍歷序列不滿足二叉搜尋樹定義,直接返回 false;(相當於判斷當前根節點左子樹)
更新父節點 root : 當棧不為空 且 riclass
solution
return
true;}
}
劍指offer 判斷單鏈表是否有環
給定乙個鍊錶,判斷鍊錶中是否有環。快慢指標法 我們知道,假設乙個鍊錶有環,那麼它就永遠走不到頭。設定有兩個指標,乙個快指標,乙個慢指標。其中,快指標一次遍歷兩個節點 慢指標遍歷乙個節點,它們都是從頭開始往後遍歷所有的節點。如果鍊錶中沒有環,那麼快指標與慢指標都會先後遍歷完所有的節點。如果鍊錶中有環,...
劍指offer 判斷出棧順序是否正確
輸入兩個整數序列,第乙個序列表示棧的壓入順序,請判斷第二個序列是否可能為該棧的彈出順序。假設壓入棧的所有數字均不相等。例如序列1,2,3,4,5是某棧的壓入順序,序列4,5,3,2,1是該壓棧序列對應的乙個彈出序列,但4,3,5,1,2就不可能是該壓棧序列的彈出序列。注意 這兩個序列的長度是相等的 ...
劍指offer 陣列
資料是最簡單的資料結構,它佔據一塊連續的記憶體並按照順序儲存資料。建立陣列時,首先指點陣列的容量大小,然後根據大小分配記憶體。缺點 空間效率不高。經常有空閒的區域滅有得到充分利用。優點 時間效率很高。可以根據時間效率高的特點,來實現簡單的雜湊表 把陣列的下標設為雜湊表的鍵值,陣列中的每乙個數字設為雜...