LeetCode中二叉樹題目總結


本文僅為博主個人總結,水平有限,歡迎大神指出不妥處。

 

關於二叉樹的相關概念可以參見二叉樹的百度百科,或binary tree Wiki

二叉樹結點類的常見定義為:

1 /* Definition for a binary tree node. */
2  struct TreeNode 
3  {
4      int val;
5      TreeNode *left;
6      TreeNode *right;
7      TreeNode(int x) : val(x), left(NULL), right(NULL) {}
8 };

 

提到二叉樹,首先要提到二叉樹的四種遍歷方式:前序遍歷、中序遍歷、后續遍歷和層次遍歷,其中前三種為一類,一般是使用棧(stack)實現,三種遍歷方式的區別在於訪問根結點的順序不同;最后一種一般使用隊列(queue)實現。這四種遍歷是很多題目的基礎,要弄懂。

一、前序遍歷、中序遍歷、后續遍歷

1、前序遍歷:訪問順序是根結點->左孩子->右孩子。迭代算法實現的主要思想為:先訪問根結點,然后若右孩子存在就將其存入棧中,若左孩子存在,則根結點沿左孩子一直到葉結點同時依次訪問;到了葉結點時, 去除棧頂結點繼續訪問,直到棧為空。Binary tree preorder traversal

2、中序遍歷:訪問順序是左孩子->根結點->右結點。迭代算法實現的主要思想為:因為先訪問左孩子(從身為葉結點的左孩子開始),所以可以利用棧先進后出的特點,我們先沿着左孩子一直將結點存入棧中,到葉結點時,從棧中取出結點開始訪問,然后取當前結點的右孩子接着進行循環,直到root為NULL且棧為空。Binary tree inorder traversal

3、后序遍歷:訪問順序是左孩子->右孩子->根結點。迭代算法實現的主要思想為:最重要的是定義一個指針記錄下前一個訪問過的,這樣可以避免重復訪問。有兩種思路:一、按照后序遍歷訪問結點的順序,將右、左孩子入棧(注意入棧順序),若到達根結點或當前結點的左、右孩子中已被訪問過,則從棧中取出結點訪問。二、可以從中序遍歷的基礎上改進,即不斷將左孩子壓入棧中,然后若當前結點的右孩子沒有被訪問過,則轉向遍歷以當前右孩子為根結點的樹,若訪問過,則取出棧頂元素訪問即可。這兩種思路中都要注意對前指針的更新。Binary tree postorder traversal

二、層次遍歷

1、一般是:利用隊列先進先出的特點,依次將結點的左、右孩子入隊,然后依次出隊訪問,以此為循環。LeetCode中有關這點為Binary tree level order traversal,不過題中要求按行輸出每一行結點的值。這里的關鍵問題是如何分層。迭代算法的實現有三種:一、定義兩個計數器:一個記錄本層結點數,一個記錄下當前層下一層的結點數,這樣遍歷完一層后輸出,然后轉向下一層,並更新結點數。二、只需一個計數器,記錄下當前行結點數,使用兩層while循環結構,每訪問完一個結點,計數器減1,直到該層中所有結點訪問;然后訪問下一行,並通過size()得到該行的結點數,以此進行循環。三、在每一層的最后向棧中壓入NULL當作該行的結束符,這樣出隊時,每遇到NULL時,就保存這一行中的結點,值得注意的時,只有隊列不為空時才壓入NULL。

2、題Binary tree level order traversal ii是上一題的延續,變化在於結果的輸出:從下到上按行輸出每行的結點值。有兩種方法,一、用上一題的結果,只是到最后,將最后的結果反轉就行;二、主體還是和上一題一樣,只是以行為單位保存每行結點時,先存入棧中,利用其先進后出的特點完成反轉輸出。

3,、題Binary tree Zigzag level order traversal可以說是二叉樹層次遍歷的延續。我們只要在以行為單位將每行結點值存入最終結果時,遇到偶數行時,將該行的結點值反轉以后存入最后結果即可。

4、題Maximum depth of binary treeThe minimum depth of binary tree的迭代法可以看成是層次遍歷的延續,求最大深度,到最底層即可,最小深度遇到第一個葉結點所在層即可。對於這兩題的遞歸解法,關鍵在於理解二叉樹深度這一概念。

三、使用前序遍歷、中序遍歷、后續遍歷中的兩種構建二叉樹

根據三種遍歷結點的順序,我們可以得到只有前序遍歷+中序遍歷、中序遍歷+后續遍歷才能實現二叉樹的構造,而前序遍歷+后續遍歷是不能構建二叉樹的,因為,沒法通過根結點的位置將左右子樹分開。這兩種方式構造二叉樹的思路相同,都是先根據根結點確定左右子樹,然后依次找到以每個結點的左右子樹,遞歸實現構造二叉樹,值得注意的,下標問題。Construct binary tree from preorder and inorder travesal Construct binary tree from inorder and postorder travesal 

四、求和問題

1、題Sum root to leaf numbers,求得是根結點到所有葉結點所形成的數(根結點為最高位)的和。Binary tree maximum path sum 中起始節點可以是任意節點。Path Sum給定一個數,判斷二叉樹中是否存在從根到葉節點,使路徑上所有結點值的和等於給定值。第一題和第三題可看成是一個遞歸實現的一個逆過程。這幾題的關鍵在於理解題意(特別是第二題)以后,使用遞歸調用解題。當然第三題可以利用后續遍歷的思想實現迭代解題。

2、題Path Sum II是題Path Sum的延續,本題中要輸出所有符合題意的路徑。迭代解法也是可以通過后續遍歷的思想解決。這里分為將這兩題分開說的原因,主要是在Path Sum II的遞歸解法上。這題的遞歸解法在后面很多題中都可以得到體現,值得注意。

五、填充問題

Populating next right pointer in each nodePopulating next right pointer in each node ii 是一個類型的,一般解法是利用層次遍歷的思想,使用隊列,來實現層與層之間的轉換。在要求不能使用額外空間時,我們可以利用其提供的next指針來實現。第一題中涉及到的幾個二叉樹的概念可見博友veli的博客。兩題的主要思路是,先保存當前行的下一行中最左端的結點以便於實現層層之間轉換。至於第二題中要注意的是要定義一個指針,實現層內的穿針引線。參考遞歸實現可以明白整個算法的結構。

六、一般二叉樹的特殊情況

Same treeSymmetric tree 是一般二叉樹的特殊情況。第一題判斷是否為相同二叉樹,可以使用兩隊列,按照層次遍歷的方式,兩二叉樹的左右孩子的入隊順序相同,判斷各種情況下是否符合;第二題判斷樹是否為對稱二叉樹,首先要理解對稱的概念,是從整體上的對稱,也可以使用兩個隊列實現判斷,不過要注意的是入隊的順序。也可以使用一個棧,入棧順序是,先左左,右右,然后左右,右左,對應的入棧,只需比較棧頂連續兩結點是否相等即可。

七、搜索二叉樹

首先要明白搜索二叉樹的概念,針對一棵二叉樹是否為搜索二叉樹有題Validate binary search tree ,要緊緊的圍繞搜索二叉樹的中序遍歷是非降序列來解題。有幾種方法:一、定義一個指針指向當前結點的前一個結點,利用二叉樹中序遍歷的思路,將兩者的值進行比較,只要前者大於后者就不是搜索二叉樹;二、可以將利用中序遍歷將二叉樹結點值都存入一個數組中,然后遍歷數組看是否為非降序型。

Unique binary search trees 給定數列,判斷能構成幾種不同的二叉搜索樹。關鍵在弄明白給定數和搜索二叉樹種類的關系(卡特蘭數)。然后依次可以寫出動態規划或遞歸的解法。Unique binary search trees ii Path Sum II的遞歸解法都是類似的,要深刻體會。

Recover binary search tree 關鍵在找到出錯的地方,有兩種方式,一:可以將結點的值存入數組中,然后排序以后,將值依次賦給對應節點;二:使用中序遍歷,找到出錯的點,然后交換即可。

其他

Balanced binary tree,這題關鍵在理解平衡二叉樹的概念:任何結點為根結點的左、右子樹的深度差不超過1(最大深度差)。

二叉樹中兩個結點最近的公共祖先匯總中講解了搜索二叉樹、一般二叉樹帶指向父結點的指針和一般二叉樹的最近公共祖先。三者依次,利用二叉搜索樹的根結點大於左孩子小於右孩子的特點;將二叉樹轉變為鏈表類型;當給定兩結點值在某一節點的左右子樹中時,為最近的公共祖先的思想。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM