LeetCode236. 二叉树的最近公共祖先

力扣

 

解题思路:

分析:

1.如果树的结构是带有parent的三叉链结构,一个节点就可以通过parent不断地向上找,直到parent为空,此时就会形成一条路径;这样就转换成了链表相交问题。

 

 

                                                         

2.如果树的结构为二叉搜索树,那么我们从根开始找:

a. 如果子节点比根要小,我们递归到左子树中去找,

b. 如果子节点比根要大,我们递归到右子树中去找。

c. 如果子节点一个比根大,一个比根小,那么它就是最近公共祖先。

 

 

3. 普通二叉树结构,从根开始搜索,查找子节点的位置 :

a. 都在左树 ,递归到左树去找,

b. 都在右树,递归到右树去找,

c. 一个在左,一个在右,根就是最近公共祖先。

                        

①  代码实现:

class Solution {
public:
    bool Find(TreeNode* root , TreeNode* x)
    {
        if(root == nullptr)
        return false;

        if(root == x)
        return true;


        return Find(root->left , x) || Find(root->right , x);
    } 
    
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) 
    {
        if(root == p || root == q) //一个节点也可以是他自己的祖先
        return root;

        bool IspInleft , IspInright , IsqInleft , IsqInright ;

        IspInleft = Find(root->left , p); //查找 p/q 在 root 的左子树还是右子树
        IspInright = !IspInleft;

        IsqInleft = Find(root->left , q);
        IsqInright = !IsqInleft;

        if(IspInleft && IsqInleft) //两个节点都在左子树 ,递归到左子树找
        {
           return  lowestCommonAncestor(root->left , p ,q);
        }
        else if(IspInright && IsqInright) //两个节点都在右子树,递归到右子树找
        {
           return  lowestCommonAncestor(root->right , p , q);
        }
        else //一个在左 , 一个在右 ,找到了
        {
          return root;
        }


    }
};

  性能分析: 

                

 

                        

②代码实现:优化到O(N),存储父节点。这里我们利用stack记录一个节点从根节点到目标节点经过的路径,最坏情况是吧全部的节点都访问,即O(N)

class Solution {
public:
    bool FindPath(TreeNode* root , TreeNode* x , stack<TreeNode*>& pt)//递归将p ,q的路径保存在栈中
    {
       if(root ==nullptr)
       return false;

       pt.push(root);

       if(root == x) //找到了
       return true;

       if(FindPath(root->left , x ,pt)) //没有找到递归到左子树
       return true;

       if(FindPath(root->right , x ,pt)) //没有找到递归到右子树
       return true;

        //左右子树都没有找到x,说明root不是路径中的节点,pop掉
        pt.pop();
        return false;
    } 
    
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) 
    {
       stack<TreeNode*>  pPath,qPath;

       FindPath(root , p , pPath); //将p的路径获取
       FindPath(root , q , qPath); //将q的路径获取

       stack<TreeNode*>* longPath = &pPath; 
       stack<TreeNode*>* shortPath = &qPath;

       if(longPath->size() < shortPath->size()) //找到最长的路径
       swap(longPath , shortPath);

       while(longPath->size() > shortPath->size()) //使两个路径长度相同
       longPath->pop();

       while(longPath->top() != shortPath->top()) //第一个相同的节点就是公共祖先
       {
           longPath->pop();
           shortPath->pop();
       }
       
       return longPath->top();
    }
};

 

③DFS

代码实现:

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
    {
      if(root == nullptr || root == p || root == q)
       return root;

        TreeNode *left = lowestCommonAncestor(root->left, p, q);
        TreeNode *right = lowestCommonAncestor(root->right, p, q);

        if(left == nullptr && right == nullptr) 
        return nullptr; // 1.

        if(left == nullptr) 
        return right; // 3.

        if(right == nullptr) 
        return left; // 4.

        return root; // 2. if(left != null and right != null)
    }
   
};

 作者:jyd
链接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/solution/236-er-cha-shu-de-zui-jin-gong-gong-zu-xian-hou-xu/
来源:力扣(LeetCode)


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值