1. 程式人生 > >【LeetCode & 劍指offer刷題】樹題3:68 樹中兩個節點的最低公共祖先

【LeetCode & 劍指offer刷題】樹題3:68 樹中兩個節點的最低公共祖先

【LeetCode & 劍指offer 刷題筆記】目錄(持續更新中...)

68 樹中兩個節點的最低公共祖先

題目:

求樹中兩個結點的最低公共祖先

思路:

考慮一下幾種情況: 1、該樹為二叉搜尋樹 二叉搜尋樹是排序樹,位於左子樹點的結點都比父結點小,而位於右子樹的結點都比父結點大,只需要從樹的根結點開始兩個輸入的結點進行比較 如果當前結點的值比兩個結點的值都大,那麼最低的公共父結點一定在左子樹,下一步就是遍歷左子樹; 如果當前結點的值比兩個結點的值都小,那麼最低的公共父結點一定在右子樹;下一步就是遍歷右子樹;
如果當前結點的值介於兩個結點的值之間,那麼它就是兩個結點的公共父結點 第一個找到的就是最低的公共父結點   235 .   Lowest Common Ancestor of a Binary Search Tree Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST.
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 binary search tree:  root = [6,2,8,0,4,7,9,null,null,3,5] Example 1: Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 Output: 6 Explanation: The LCA of nodes 2 and 8 is 6 . Example 2: Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 Output: 2 Explanation: The LCA of nodes 2 and 4 is 2 , 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 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 ;     } };