LeetCode:(236. 二叉树的最近公共祖先)

题目

题目链接

在这里插入图片描述
思路1:
该方法比较巧妙,就是如果p,q在一个结点的两边,那么他就是最近的公共祖先。使用这个思路,就是找这个结点是不是在左右两边。
如果pq都在左边/右边,就再去左/右子树去寻找,直到pq分别在左右子树即可。

在这里插入图片描述

class Solution {
public:
// 找x在没在该树下面,在返回true,不再返回false
    bool IsInTree(TreeNode* root, TreeNode* x) 
    {
        if(root == nullptr)
        {
            return false;
        }
        //注意该返回方式,很巧妙,找到就结束了。
        return root == x
        || IsInTree(root->left, x)
        || IsInTree(root->right, x);
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        
        if(root == nullptr)
        {
            return nullptr;
        }
        //只要有一个结点是root,该结点必是祖先
        if(p == root || q == root)
        {
            return root;   //这是出口1
        }

        //根不是,这种方法也很巧妙,看是否在左边,不再就在右边。
        bool pLeft = IsInTree(root->left,p);
        bool pRight = !pLeft;

        bool qLeft = IsInTree(root->left, q);
        bool qRight = !qLeft;

        if((pLeft && qRight) || (pRight && qLeft))
        {
            return root;    //这是出口2
        }
        else if(pLeft&&qLeft)  //都在左边
        {
            return lowestCommonAncestor(root->left, p, q);    //去找出口,找到直接结束了
        }
        else      //都在右边
        {
            return lowestCommonAncestor(root->right, p, q);
        }
    }
};

难点:虽然思路很清晰,但是考验代码和递归的控制能力。(找到该节点就不再递归了,应该立马结束,应该怎么控制?可以有||,可以直接return)
好好理解,希望能举一反三!!!

思路2:
分别找到p,q两个结点的路径,当成链表相交问题。长链表先走差距步,然后再一块走。地址相同结点即为祖先结点。

class Solution {
public:
bool GetPath(TreeNode* root, stack<TreeNode*>& path, TreeNode* x)
{
    if(root == nullptr)
    {
        return false;
    }
    path.push(root);
    if(root == x)
    {
        return true;
    }
    if(GetPath(root->left, path, x))
    {
        return true;
    }
    if(GetPath(root->right, path, x))
    {
        return true;
    }
    path.pop();
    return false;
}   

    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        stack<TreeNode*> pPath;
        stack<TreeNode*> qPath;
        GetPath(root, pPath, p);        
        GetPath(root, qPath, q);
        while(pPath.size()!=qPath.size())
        {
            if(pPath.size()>qPath.size())
            {
                pPath.pop();
            }
            else
            {
                qPath.pop();
            }
        }
        while(pPath.top()!=qPath.top())
        {
            pPath.pop();
            qPath.pop();
        }
        return qPath.top();
    }
};

难点:

  1. 递归去找结点的路径,这个方法也很巧妙,注意揣摩。
  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值