两节点的最小公共祖先LCA

一、二叉搜索树中两节点的最小公共祖先:

    最初级的题目,在一颗二叉搜索树中寻找两节点的最小公共祖先。根据二叉搜索树的特征,从根节点开始查找,若两节点的val值都小于当前节点,则他们的最小公共祖先就去左子树找,若两节点的val值都大于当前节点,则他们的最小公共祖先就去右子树找。直到一个节点的值小于当前节点,另一个节点的值大于当前节点,那么当前节点为最小公共祖先,即为找到了可以返回了。

c++代码:

TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) 
{
        if(root == NULL)
            return root;
        if (p->val<root->val && q->val<root->val)
            return lowestCommonAncestor(root->left, p, q);
        else if(p->val>root->val && q->val>root->val)
            return lowestCommonAncestor(root->right, p, q);
        return root;       
}

 

二、二叉树中两节点的最小公共祖先:

    1、二叉树有指向父节点的指针:当二叉树中有指向父节点的指针时,可以倒过来看待这个问题,即为求两个链表的公共节点。从当前节点开始往根节点数,记录总共有多少个节点,记下数字。然后大数字的链表上先走几步到数字一样,再两节点都一起往根节点走,第一个相同的节点即为最小公共子节点。参见求链表相交的部分

   2、二叉树没有指向父节点的指针:

    这是普通的二叉树中求两节点的最小公共祖先。

思路一:二叉树中两节点无外乎这样几种情况,两节点p和q相等;p是q的子树或子树中的节点;q是p的子树或子树中的节点;q和p是两支子树,这时候可以递归找到他们的父节点继续前面的思路;

C++代码如下:

 bool ischild(TreeNode *pa, TreeNode *ch)
    {
        if (ch == pa || pa==nullptr)
            return false;
        if (pa->left==ch || pa->right==ch)
            return true;
        return ischild(pa->left, ch)||ischild(pa->right, ch);
    }
    TreeNode* find_pa(TreeNode* root, TreeNode*cur)
    {
        if (root->left == cur || root->right==cur)
            return root;
        if (ischild(root->left, cur))
            return find_pa(root->left, cur);
        else
            return find_pa(root->right, cur);
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (p==q)
            return q;
        if (ischild(p, q))
            return p;
        if (ischild(q,p))
            return q;
        TreeNode *p_pa=find_pa(root, p);
        TreeNode *q_pa=find_pa(root, q);
        if (ischild(p_pa, q_pa) || p_pa==q_pa)
            return p_pa;
        else if(ischild(q_pa, p_pa))
            return q_pa;
        else
            return lowestCommonAncestor(root, p_pa, q_pa);
    }

 

思路二:简单直接一点。当root非空时,不断从其左右子数搜索,①如果两节点都在其左子树,对其左子树节点递归搜索;②如果两节点都在其右子树,对其右子树节点递归搜索;③如果一个节点在左子树一个节点在右子树,则当前节点即为最小公共祖先。

C++代码如下:

TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (root==NULL || root == p|| root==q)
            return root;
        if(p == q)
            return p;
        TreeNode* left = lowestCommonAncestor(root->left, p, q);
        TreeNode* right = lowestCommonAncestor(root->right,p,q);
        if (left!=NULL && right!=NULL)
            return root;
        else if(left == NULL)
            return right;
        return left;
    }

 

三、普通树中两节点的最小公共祖先:

    1、树有指向父节点的指针:这种情况等同求链表的公共节点。同上参见求链表相交的部分

    2、树没有指向父节点的指针:此种情况我觉得可以参见上述第二种普通二叉树求最小公共祖先(LCA)的方法,只是每次要在当前节点的每一个子树搜索。然而现在记录另外一种方法,参加剑指offer50题:可以用两个辅助空间,在当前数中搜索两个节点的路经并存下来。然后从根节点开始依次往后比较,记录下最后一个相等的节点即为最小公共祖先。

C++代码:

寻找路经:

 bool GetNodePath(TreeNode *pRoot, TreeNode *pNode, list<TreeNode*>&path){
 
   if (pRoot==pNode)
 
     return true;
 
   path.push_back(pRoot);
 
   bool found=false;
 
   vector<TreeNode*>::iterator i=pRoot->m_vChildren.begin();
 
   while(!found && i!=pRoot->m_vChildren.end())
 
   {  found = GetNodePath(*i, pNode, path); ++i}
 
   if(!found)
 
    path.pop_back();
 
   return found;

 }

 

在两个路经中寻找最后的公共节点:

TreeNode *GetLastCommonNode(const list<TreeNode*>&path1,const list<TreeNode*>&path2 )
  
 {
 
  list<TreeNode*>::const_iterator iterator1=path1.begin();
 
  list<TreeNode*>::const_iterator iterator2=path2.begin();
 
  TreeNode* pLast=NULL;
 
   while(iterator1!=path1.end() && iterator2!=path2.end())
 
   {
 
     if (*iterator1 == *iterator2)//按照值在寻找,而非节点。。其实也是可以按照节点来寻找的

       pLast = *iterator1;  //这里按照我的理解 也应该直接赋值 没有解引用 因为迭代器本身就是一个指针啊
 
     ++iterator1;++iterator2;
 
   }
 
   return pLast;
 
 }

 

寻找最小公共祖先:

TreeNode *GetLastCommonParent(TreeNode* pRoot, TreeNode* pNode1, TreeNode* pNode2)
 
 {
 
   if(pRoot==NULL || pRoot==pNode1 || pRoot==pNode2) return pRoot;
 
   if (pNode1 == pNode2)  return pNode1;

  List<TreeNode*>path1, path2;
 
   GetNodePath(pRoot,pNode1,path1);
 
   GetNodePath(pRoot,pNode2,path2);
 
   return GetLastCommonNode(path1,path2);
 
 }

 

原文链接: https://www.cnblogs.com/weiyi-mgh/p/6612146.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    两节点的最小公共祖先LCA

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/251365

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月14日 上午5:14
下一篇 2023年2月14日 上午5:15

相关推荐