【LeetCode & 劍指offer刷題】樹題3:68 樹中兩個節點的最低公共祖先
阿新 • • 發佈:2019-01-05
【LeetCode & 劍指offer 刷題筆記】目錄(持續更新中...)
68 樹中兩個節點的最低公共祖先
題目:
求樹中兩個結點的最低公共祖先思路:
考慮一下幾種情況: 1、該樹為二叉搜尋樹 二叉搜尋樹是排序樹,位於左子樹點的結點都比父結點小,而位於右子樹的結點都比父結點大,只需要從樹的根結點開始和兩個輸入的結點進行比較。 如果當前結點的值比兩個結點的值都大,那麼最低的公共父結點一定在左子樹,下一步就是遍歷左子樹; 如果當前結點的值比兩個結點的值都小,那麼最低的公共父結點一定在右子樹;下一步就是遍歷右子樹;- All of the nodes' values will be unique.
- p and q are different and both values will exist in the BST.
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ /* 問題:二叉搜尋樹的最低公共祖先 方法:遞迴法 如果根節點的值大於p和q之間的較大值,說明p和q都在左子樹中,那麼此時我們就進入根節點的左子節點繼續遞迴,如果根節點小於p和q之間的較小值,說明p和q都在右子樹中,那麼此時我們就進入根節點的右子節點繼續遞迴,如果都不是,則說明當前根節點就是最小共同父節點,直接返回即可 */ class Solution { public : TreeNode * lowestCommonAncestor ( TreeNode * root , TreeNode * p , TreeNode * q ) { if (! root ) //空結點時返回空 return nullptr ; //從根結點開始遞迴 if ( root -> val > max ( p -> val , q -> val )) //如果p,q在當前結點左子樹,則對左子樹遍歷 return lowestCommonAncestor ( root -> left , p , q ); else if ( root -> val < min ( p -> val , q -> val )) //如果p,q在當前結點右子樹,則對右子樹遍歷 return lowestCommonAncestor ( root -> right , p , q ); else //如果當前結點在p,q之間,則為最低公共父結點(因為從上往下在遍歷,故遇到的第一個滿足此條件的就是) return root ; } }; 2、該樹為二叉樹,結點中有指向父結點的指標 有了父結點,就可以找到任意結點到根結點的路徑;因此: 分別找到從兩個結點開始到根結點的路徑,即兩個連結串列; 然後找到兩個連結串列的第一個公共結點,就是最低的公共父結點; 3、該樹為普通的樹 從根結點開始,dfs,分別找到到達兩個結點的路徑; 然後 找到兩條路徑的最後一個公共結點 ,就是最低的公共父結點; Lowest Common Ancestor of a Binary Tree Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According to the definition of LCA on Wikipedia : “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself ).” Given the following binary tree: root = [3,5,1,6,2,0,8,null,null,7,4] Example 1: Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 Output: 3 Explanation: The LCA of of nodes 5 and 1 is 3. Example 2: Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 Output: 5 Explanation: The LCA of nodes 5 and 4 is 5 , since a node can be a descendant of itself according to the LCA definition. Note:
- All of the nodes' values will be unique.
- p and q are different and both values will exist in the binary tree.
C++ /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ /* 問題:普通二叉樹的最低公共祖先 方法:遞迴法 這道題是普通是二叉樹,不是二叉搜尋樹,所以就不能利用其特有的性質,所以我們只能在二叉樹中來搜尋p和q,從左右子樹中分別找p,q,如果對於某個結點,左右分別有p,q,則說明該結點為最低公共祖先 題目中沒有明確說明p和q是否是樹中的節點,如果不是,應該返回NULL,而下面的方法就不正確了 不好理解 */ class Solution { public : TreeNode * lowestCommonAncestor ( TreeNode * root , TreeNode * p , TreeNode * q ) { if (root == nullptr || p == root || q == root) //如果p==root或者q==root,說明找到了p和q return root ; TreeNode * left = lowestCommonAncestor ( root -> left , p , q ); //找左子樹中是否存在p或q,存在時返回p或q或者p,q的祖先結點,不存在時返回nullptr TreeNode * right = lowestCommonAncestor ( root -> right , p , q ); //找右子樹中是否存在p或q if ( left && right ) //left和right分別有p或q,則其父結點root為p,q的最低公共祖先 return root ; else return left ? left : right ; //left同時有p,q,則left為公共祖先,(若left為空,則right為公共祖先) } }; /* 改進:在找完左子樹的共同父節點時如果結果存在,且不是p或q, 那麼不用再找右子樹了,直接返回這個結果即可,同理,對找完右子樹的結果做同樣處理,參見程式碼如下: */ class Solution { public : TreeNode * lowestCommonAncestor ( TreeNode * root , TreeNode * p , TreeNode * q ) { if (! root || p == root || q == root ) return root ; TreeNode * left = lowestCommonAncestor ( root -> left , p , q ); if ( left && left != p && left != q ) return left ; //如果left不為空且不是p或q,則其為公共祖先 TreeNode * right = lowestCommonAncestor ( root -> right , p , q ); if ( right && right != p && right != q ) return right ; if ( left && right ) //left和right分別有p或q,則其父結點root為p,q的最低公共祖先 return root ; else return left ? left : right ; } };