236.二叉树的最近公共祖先(递归)

在这里插入图片描述

在这里插入图片描述
解题思路:

暴力,递归

1 定义辅助函数,判断以root为节点的树中是否包含p或q节点。

2 假如root不等于p或者q节点,那么看看左子树包含它们吗,右子树包含它们吗;
a 假如左右子树都包含节点,说明各包含一个,返回当前root就可以了;
b 假如只有左子树包含,说明两个节点都在左子树,那么就递归到左子树;
c 假如只有右子树包含,说明两个节点都在右子树,那么就递归到右子树;

假如遇到root为p、q本身为最近公共祖先的情况,返回root本身;
有人会考虑到root是p、q本身,那另一个节点可能在右边啊,这里不会,因为遇到这种情况之前,会遇到上面的a情况,已经return 结果了。(所以产生了下面的第二个版本的代码)

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        //假如root等于p或者q,那么只要看另一个节点是否在root的左右子树中,在的话返回root
        if(root==p||root==q){
            bool flag=hasNode(root->left,p,q)
                    ||hasNode(root->right,p,q);
            if(flag)
                return root;
        }

        //假如root不等于p和q,判断是否在p、q是否分别在左右子树,是的话root就是最近公共祖先
        TreeNode* node;
        if(root!=p&&root!=q){
            bool flag1=hasNode(root->left,p,q);
            bool flag2=hasNode(root->right,p,q);
            if(flag1&&flag2)
                return root;
            //假如只有flag1为真,说明p、q都在左子树,在左子树找
            if(flag1&&!flag2)
                node=lowestCommonAncestor(root->left,p,q);
            //假如只有flag2为真,说明p、q都在右子树,在右子树找
            if(flag2&&!flag1)
                node=lowestCommonAncestor(root->right,p,q);
        } 
        return node;
    }

    //辅助函数,判断以root为根的树中是否有p、q节点
    bool hasNode(TreeNode*root,TreeNode* p, TreeNode* q){
        if(root==p||root==q) return true;
        if(!root)return false;

        bool flag1=hasNode(root->left,p,q);
        bool flag2=hasNode(root->right,p,q);
        return flag1||flag2;
    }
};

版本2

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        //假如root不等于p和q,判断是否在p、q是否分别在左右子树,是的话root就是最近公共祖先
        TreeNode* node=root;
        if(root!=p&&root!=q){
            bool flag1=hasNode(root->left,p,q);
            bool flag2=hasNode(root->right,p,q);
            if(flag1&&flag2)
                return root;
            //假如只有flag1为真,说明p、q都在左子树,在左子树找
            if(flag1&&!flag2)
                node=lowestCommonAncestor(root->left,p,q);
            //假如只有flag2为真,说明p、q都在右子树,在右子树找
            if(flag2&&!flag1)
                node=lowestCommonAncestor(root->right,p,q);
        } 
        return node;
    }

    //辅助函数,判断以root为根的树中是否有p、q节点
    bool hasNode(TreeNode*root,TreeNode* p, TreeNode* q){
        if(root==p||root==q) return true;
        if(!root)return false;

        bool flag1=hasNode(root->left,p,q);
        bool flag2=hasNode(root->right,p,q);
        return flag1||flag2;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值