【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 ;
    }
};
 
 

猜你喜欢

转载自www.cnblogs.com/wikiwen/p/10225780.html