題目:
思路一:遞迴
分析:這個題目首先想到的是能自底向上查詢,就可以找到公共祖先了。所以採用後序遍歷,最先處理葉子節點
判斷節點是不是最近的公共祖先:乙個節點的左右子樹分別出現p和q,或者節點是p或者q,該節點的左子樹或者右子樹出現p或者q;
分析2和5 的公共祖先
根據後序遍歷處理順序 ,先處理節點1,因為節點1的左孩子、右孩子、本身都不為p或q,處理結果返回false,再處理6,返回結果也是false,接著處理5,因為節點本身為5,(目標節點)返回true,接著處理7,因為右孩子為true,所以處理結果為true,同樣處理10,返回值也為true,接著處理2,返回為true,接著處理3,返回值為true,最後處理8,因為節點的左孩子和右孩子都為true,則8就是公共祖先,所以公共祖先找到
例如下圖思路也是如此(找9和10的公共祖先)
步驟:1.、遞迴三部曲:(有返回值的遞迴)遍歷整棵樹
class
solution
public
: treenode*
lowestcommonancestor
(treenode* root, treenode* p, treenode* q)
};
思路二:遞迴(後序遍歷)
分析:查詢6和5,根據根節點的處理順序,先遞迴左子樹,沒找到就返回空,再遞迴右子樹,先找到6,就將6作為左子樹的返回值,返回給上一層,再處理5,將5作為右子樹的返回值返回給上一層;接著處理7節點,由於左子樹和右子 樹的返回值都不為空,就說明公共祖先,就返回該節點,一層一層向上返回。
查詢10和7:訪問8,再訪問10,因為10是目標節點,返回該節點,讓其作為根節點的左子樹返回值,再遞迴右子樹,如果其右子樹沒找到目標節點就返回空給根節點的右子樹返回值,然後對這兩個返回值進行判斷,因為左子樹返回值不為空,右子樹返回值為空,就將左子樹返回值返回(說明:8節點的左子樹遍歷找到乙個節點後,再遍歷8的右子樹,沒有找到目標節點說明目標節點在8節點的左子樹且在10的下層,所以10一定是根節點,如果8節點的右子樹右目標節點,則右子樹的返回值就是目標節點,然後根據左子樹和右子樹返回值不為空,返回8節點)
步驟:遞迴三部曲:
1、函式引數和返回值
函式引數為根節點和目標節點,因為要找到公共祖先節點,返回值為節點
2、函式結束的條件
如果節點為目標節點或為空,就返回該節點
3、單層邏輯
遞迴左子樹,返回左子樹的值
遞迴右子樹,返回右子樹的值
如果左子樹和右子樹都不為空,就返回該節點;如果其中乙個不為空,就返回不為空的;都為空,就返回空
class
solution
else}}
;
小結:為什麼這個遞迴函式有返回值還會遍歷完整棵樹
搜尋一條邊的寫法:
if(遞迴函式(root-
>left)
)return;if
(遞迴函式(root-
>right)
)return
;
搜尋整棵樹的寫法
```cpp
left=遞迴函式(root-
>left);
right=遞迴函式(root-
>right);
```left和right的處理邏輯
兩者的區別: 「在遞迴函式有返回值的情況下:如果要搜尋一條邊,遞迴函式返回值不為空的時候,立刻返回;如果搜尋整個樹,直接用乙個變數left、right接住返回值,這個left、right後序還有邏輯處理的需要,也就是後序遍歷中處理中間節點的邏輯(也是回溯)」 LeetCode236 二叉樹最近祖先
思考 這個函式就是查詢p,q兩個節點的祖先,然後給了這棵樹的root,1 它先進行判斷,根節點是不是null 或者根節點是否是p q,要是有乙個是,那祖先就肯定是root 2 它用了遞迴的思想去查詢左右兩個子樹,因為pq的祖先要麼在左邊,要麼就在右邊,所以肯定能找到乙個祖先。3 若找到的left 子...
LeetCode 236 二叉樹最近公共祖先
leetcode 236 二叉樹最近公共祖先 236.二叉樹的最近公共祖先 題目描述 給定乙個二叉樹,找到該樹中兩個指定節點的最近公共祖先。解體思路 分兩部分解決 第一部分 實現判斷兩個結點包含於某根節點的子樹內 第二部分 先序遍歷二叉樹,如果根節點的子樹包含qp目標結點 傳入左孩子,進行遞迴。傳入...
leetcode 236 二叉樹最近公共祖先
給定乙個二叉樹,找到該樹中兩個指定節點的最近公共祖先。例如,給定如下二叉樹 root 3,5,1,6,2,0,8,null,null,7,4 示例 1 輸入 root 3,5,1,6,2,0,8,null,null,7,4 p 5,q 1 輸出 3 解釋 節點 5 和節點 1 的最近公共祖先是節點 ...