【leetcode】【medium】236. Lowest Common Ancestor of a Binary Tree

本文介绍了二叉树中寻找两个节点的最低公共祖先(LCA)的两种递归方法。第一种方法通过查找两个节点的路径,然后找到这两条路径的第一个分叉点;第二种方法通过标记,寻找第一个满足其子树包含两个目标节点的根节点。

236. Lowest Common Ancestor of a Binary Tree

Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.

According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”

Given the following binary tree:  root = [3,5,1,6,2,0,8,null,null,7,4]

Example 1:

Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
Output: 3
Explanation: The LCA of nodes 5 and 1 is 3.

Example 2:

Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
Output: 5
Explanation: The LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.

Note:

  • All of the nodes' values will be unique.
  • p and q are different and both values will exist in the binary tree.

题目链接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/

 

思路

两种方法都可以用递归和非递归实现,这里只做了递归方法。

法一:找路径,再找两个链的最低共同点

先找到两个节点的路径,然后两条路径都从根节点开始,向下找第一个分叉点。

/**
 * 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) {
        if(!root || !p || !q) return NULL;
        auto pp = path(root, p);
        auto pq = path(root, q);
        TreeNode* res;
        while(!pp.empty() && !pq.empty() && pp.top() == pq.top()){
            res = pp.top();
            pp.pop();
            pq.pop();
        }
        return res;
    }
    stack<TreeNode*> path(TreeNode* root, TreeNode* p ){
        stack<TreeNode*> res;
        if(!root) return res;
        if(root==p){
            res.push(root);
            return res;
        }else{
            auto l = path(root->left, p);
            auto r = path(root->right, p);
            if(l.size()>0){
                l.push(root);
                return l;
            }
            else if(r.size()>0){
                r.push(root);
                return r;
            }
            else return res;
        }
        
    }
};

法二:标帜

找第一个满足子树上有两个节点的根节点。

/**
 * 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* res = NULL;
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(!root || !p || !q) return NULL;
        find(root, p, q);
        return res;
    }
    bool find(TreeNode* root, TreeNode* p, TreeNode* q){
        if(!root) return NULL;
        int l = (find(root->left, p, q))?1:0;
        int r = (find(root->right, p, q))?1:0;
        int m = (root==p || root==q)?1:0;
        cout<<root->val<<":"<<l<<","<<r<<","<<m<<endl;
        if(l+r+m>=2){
            res = root;
            cout<<root->val;
        }
        return (l+r+m)>0;
    }
};

 

源码地址: https://pan.quark.cn/s/d1f41682e390 miyoubiAuto 米游社每日米游币自动化Python脚本(务必使用Python3) 8更新:更换cookie的获取地址 注意:禁止在B站、贴吧、或各大论坛大肆传播! 作者已退游,项目不维护了。 如果有能力的可以pr修复。 小引一波 推荐关注几个非常可爱有趣的女孩! 欢迎B站搜索: @嘉然今天吃什么 @向晚大魔王 @乃琳Queen @贝拉kira 第三方库 食用方法 下载源码 在Global.py中设置米游社Cookie 运行myb.py 本地第一次运行时会自动生产一个文件储存cookie,请勿删除 当前仅支持单个账号! 获取Cookie方法 浏览器无痕模式打开 http://user.mihoyo.com/ ,登录账号 按,打开,找到并点击 按刷新页面,按下图复制 Cookie: How to get mys cookie 当触发时,可尝试按关闭,然后再次刷新页面,最后复制 Cookie。 也可以使用另一种方法: 复制代码 浏览器无痕模式打开 http://user.mihoyo.com/ ,登录账号 按,打开,找到并点击 控制台粘贴代码并运行,获得类似的输出信息 部分即为所需复制的 Cookie,点击确定复制 部署方法--腾讯云函数版(推荐! ) 下载项目源码和压缩包 进入项目文件夹打开命令行执行以下命令 xxxxxxx为通过上面方式或取得米游社cookie 一定要用双引号包裹!! 例如: png 复制返回内容(包括括号) 例如: QQ截图20210505031552.png 登录腾讯云函数官网 选择函数服务-新建-自定义创建 函数名称随意-地区随意-运行环境Python3....
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值