[C++] LeetCode 236. 二叉树的最近公共祖先

题目

给定一棵二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义: “对于有根树T的两个结点uv,最近公共祖先表示一个结点x,满足xuv的祖先且x的深度尽可能大。”(一个节点也可以是它自己的祖先)
这里写图片描述
例如,节点5和节点1的最近公共祖先是节点3;节点5和节点4的最近公共祖先是节点5,因为根据定义,一个节点可以是它自己的祖先。

题解

这道题应该是面试常考题。

方法一

可以考虑直接用两个数组分别记录uv的路径,然后遍历两个路径找公共祖先。将寻找最近公共祖先转换为两个数组找公共节点。

/**
 * 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:
    bool getAncestor(TreeNode* root,TreeNode *p,vector<TreeNode*> &vec){
        if(root==NULL) return false;
        if(root==p){
            vec.push_back(root);
            return true;
        }
        if(getAncestor(root->left,p,vec)||getAncestor(root->right,p,vec)){
            vec.push_back(root);
            return true;
        }
        return false;

    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        vector<TreeNode*> vp,vq;
        getAncestor(root,p,vp);
        getAncestor(root,q,vq);
        int n=vp.size(),m=vq.size();
        while(n>0&&m>0&&vp[n-1]==vq[m-1]){
            n--;
            m--;
        }
        return vp[n];
    }
};

方法二

如果不能使用辅助数组来记录路径。那么可以考虑同时在一棵二叉树中查找pq两个节点,如果只找到了p节点则返回1,如果只找到了q节点,则返回2,如果同时找到pq节点,则返回3,其余情况返回0,那么根据返回值就可以判断是否是公共祖先。具体代码如下:

/**
 * 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:
    int getRes(TreeNode *root,TreeNode *p,TreeNode* q,TreeNode *&res){
        if(root==NULL||res!=NULL) return 0;
        int l=getRes(root->left,p,q,res);
        if(l==3) return 3;  //左子树同时找到p和q
        int r=getRes(root->right,p,q,res);
        if(r==3) return 3;  //右子树同时找到p和q
        //左子树和右子树分别找到p和q,则当前节点为最近公共祖先
        if((l==1&&r==2)||(l==2&&r==1)){
            res=root;
            return 3;
        }
        //当前节点为p,且左子树或者右子树找到q。或者当前节点为q,且左子树或者右子树找到p
        if((root==p&&(l==2||r==2))||(root==q&&(l==1||r==1))){
            res=root;
            return 3;
        }
        if(root==p||(l==1||r==1)) return 1;
        else if(root==q||(l==2||r==2)) return 2;
        else return 0;
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        TreeNode *res=NULL;
        getRes(root,p,q,res);
        return res;
    }
};
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值