劍指Offer 面試題 樹和二叉樹

2021-09-24 01:37:55 字數 3254 閱讀 2107

題目描述:輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列和中序遍歷序列,則重建二叉樹並返回。

基礎知識:在二叉樹的前序遍歷序列中,第乙個數字總是樹的根節點的值。在中序遍歷序列中,根節點的值在序列的中間,左子樹的節點的值位於根節點的值的左邊,右子樹的節點的值位於根節點的值的右邊。

思路:首先由前序遍歷序列得到根節點的值,然後遍歷中序遍歷序列,找到根節點在中序遍歷序列中的位置,那麼位於根節點的值的左邊的便是左子樹,位於根節點的值的右邊的便是右子樹。最後,通過遞迴,使用同樣的辦法去構建左子樹和右子樹。

思路:如果乙個節點有右子樹,那麼它的下乙個節點就是它的右子樹中的最左子節點。也就是說,從右子節點出發一直沿著指向左子節點的指標,我們就能找到它的下乙個節點。

如果乙個節點沒有右子樹,且該節點是它父節點的左子節點,那麼它的下乙個節點就是它的父節點。

如果乙個節點沒有右子樹,且該節點是它父節點的右子節點,那麼我們可以沿著父節點的指標一直向上遍歷,直到找到乙個是它父節點的左子節點的節點。如果這樣的節點存在,那麼這個節點的父節點就是我們要找的下乙個節點。

題目描述:輸入兩棵二叉樹a,b,判斷b是不是a的子結構。(ps:我們約定空樹不是任意乙個樹的子結構)

思路:第一步:在樹a中找到和樹b的根節點的值一樣的節點r。這實際上就是樹的遍歷,可以用迴圈,也可以用遞迴(**簡潔)。

第二步:判斷樹a 中以r為根節點的值是不是和樹b一樣的結構。同樣採用遞迴的思路,如果節點r的值和樹b的根節點的值不相同,則以r為根節點的子樹和樹b肯定不具有相同的節點;如果它們的值相同,則遞迴判斷他們各自的左右節點的值是不是相同。遞迴的終止條件是我們到達了樹a或樹b的葉節點。

題目描述:操作給定的二叉樹,將其變換為源二叉樹的映象。

思路:前序遍歷樹的每個節點,如果遍歷到的節點有子節點,就交換它的兩個子節點。當交換完所有非葉子節點的左右子節點之後,就得到了樹的映象。

題目描述:請實現乙個函式,用來判斷一顆二叉樹是不是對稱的。注意,如果乙個二叉樹同此二叉樹的映象是同樣的,定義其為對稱的。

思路:(前序遍歷)針對前序遍歷定義一種對稱的遍歷演算法,即先遍歷父節點,再遍歷它的右子節點,最後遍歷它的左子節點。如果二叉樹的前序遍歷序列和對稱的前序遍歷序列一樣,則說明該二叉樹是對稱的。但要特別注意節點為空的情況。

題目描述:從上往下列印出二叉樹的每個節點,同層節點從左至右列印。

思路:(佇列)通過舉例分析,我們可以發現從上到下列印二叉樹的規律:每次列印乙個節點的時候,如果該節點有左右子節點,則把它們加入到佇列的末尾。接下來到佇列的頭部取出最早進入佇列的節點,重複前面的列印操作,直到佇列中的所有節點都被列印出來。

拓展訓練1:把二叉樹列印成多行

題目描述:從上到下按層列印二叉樹,同一層結點從左至右輸出。每一層輸出一行。

思路:(佇列)同樣採用佇列來儲存要列印的節點。我們定義兩個變數,乙個表示當前層還沒列印的節點數,乙個表示下一層節點的數目。當當前層列印的數目為0時,把下一層的節點數賦值給當前層列印數目,並將其置為0,然後接著列印下一層。

拓展訓練2:按之字形順序列印二叉樹

題目描述:請實現乙個函式按照之字形列印二叉樹,即第一行按照從左到右的順序列印,第二層按照從右至左的順序列印,第三行按照從左到右的順序列印,其他行以此類推。

思路:(棧)通過舉例分析,我們可以發現按之字形順序列印二叉樹的規律:需要兩個棧。當我們在列印某一層的節點時,把下一層的子節點儲存到對應的棧裡。如果當前列印的是奇數層,則先儲存左子節點再儲存右子節點到第乙個棧裡;如果當前列印的是偶數層,則先儲存右子節點再儲存左子節點到第二個棧裡。

題目描述:輸入乙個整數陣列,判斷該陣列是不是某二叉搜尋樹的後序遍歷的結果。如果是則輸出yes,否則輸出no。假設輸入的陣列的任意兩個數字都互不相同。

基礎知識:在後序遍歷得到的序列中,最後乙個數字是樹的根節點的值。陣列中前面的數字可以分為兩部分:第一部分是左子樹節點的值,他們都比根節點的值小;第二部分是右子樹節點的值,它們都比根節點的值大。

思路:如果序列陣列為空或長度小於等於0,返回false;

我們可以根據後序遍歷序列的特點得到根節點、左子樹和右子樹。在遍歷過程中,得到的左子樹節點的值肯定都比根節點小,如果右子樹中發現有比根節點的值小的節點,返回false;

我們定義兩個布林值left和right,通過同樣的方法分別判斷左右子樹是不是二叉搜尋樹。

最後返回布林值(left&&right)

題目描述:輸入一顆二叉樹的跟節點和乙個整數,列印出二叉樹中結點值的和為輸入整數的所有路徑。路徑定義為從樹的根結點開始往下一直到葉結點所經過的結點形成一條路徑。(注意: 在返回值的list中,陣列長度大的陣列靠前)

思路:(棧)通過舉例分析,我們發現規律:當用前序遍歷的方式訪問到某一節點時,我們把該節點新增到路徑上,並累加該節點的值。如果該節點為葉節點,並且路徑中節點值的和剛好等於輸入的整數,則當前路徑符合要求,我們把它列印出來。如果當前節點不是葉節點,我們繼續訪問它的子節點。當前節點訪問結束後,遞迴函式將自動回到它的父節點。因此,我們在函式退出之前要在路徑上刪除當前節點並減去當前節點的值,以確保返回父節點時路徑剛好是從根節點到父節點。(用棧來儲存路徑)

題目描述:請實現兩個函式,分別用來序列化和反序列化二叉樹。

思路:序列化和反序列化——前序l遍歷,遞迴,空指標轉換為"$",包括葉節點的左右指標也轉換為"$"。

題目描述:給定一棵二叉搜尋樹,請找出其中的第k大的結點。例如, (5,3,7,2,4,6,8)    中,按結點數值大小順序第三大結點的值為4。

思路:(中序遍歷)如果按照中序遍歷的順序遍歷一棵二叉搜尋樹,則遍歷序列的數值是遞增排序的。

題目描述:輸入一棵二叉樹,求該樹的深度。從根結點到葉結點依次經過的結點(含根、葉結點)形成樹的一條路徑,最長路徑的長度為樹的深度。

思路:(遞迴)如果一棵樹只有乙個節點,那麼它的深度就是1。如果根節點有左子樹或右子樹或都有,那麼它的深度就是左右子樹中深度較大的值加1。(通過遞迴得到左右子樹的深度。)

拓展訓練:平衡二叉樹

題目描述:輸入一棵二叉樹,判斷該二叉樹是否是平衡二叉樹。

基礎知識:平衡二叉樹必須滿足兩個條件:1)左右子樹的高度差不能大於1 ;  2)每個根節點下面的左右子樹也必須滿足平衡二叉樹的性質。

思路:(後序遍歷)我們通過後序遍歷的方式遍歷二叉樹的每個節點,那麼在遍歷到乙個節點的時候,已經遍歷了它的左、右子樹。只要在遍歷每個節點的時候記錄它的深度,我們就可以一邊遍歷,一邊判斷每個節點是不是平衡的。

end

《劍指Offer》面試題 平衡二叉樹

題目 輸入乙個二叉樹的根節點,判斷該樹是不是平衡二叉樹。如果某二叉樹中任意節點的左右子樹的深度相差不超過1,那麼它就是一棵平衡二叉樹。思路 用後序遍歷實現 先遍歷節點的左右子樹,左右子樹都平衡才來判斷該節點是否平衡,如果左右子樹中有不平衡的,則直接返回false,避免了從上往下逐個節點地計算深度帶來...

《劍指Offer》面試題 二叉樹的深度

題目描述 輸入一棵二叉樹,求該樹的深度。從根結點到葉結點依次經過的結點 含根 葉結點 形成樹的一條路徑,最長路徑的長度為樹的深度。思路 此題的遞迴思想比較簡單,直接用遞迴將根節點的深度轉換為求左右子孩子的深度的較大值 1,根節點的深度等於max 左孩子的深度,右孩子的深度 輸入 第一行輸入有n,n表...

劍指Offer 面試題19 映象二叉樹

操作給定的二叉樹,將其變換為源二叉樹的映象。以題目中的兩棵樹為例 就是先序遍歷這棵樹,如果當前正在遍歷的節點有子結點 無論是左還是右 就交換兩個子節點,當交換完所有的非葉子結點的左右子結點的時候,就得到了樹的映象.具體過程如下所示 注意6和10交換之後,第三層結點的排列順序 遞迴實現 public ...