前往小程序,Get更优阅读体验!
立即前往
社区首页 >专栏 >求二叉树的最近公共祖先,倘若不是二叉树呢?

求二叉树的最近公共祖先,倘若不是二叉树呢?

作者头像
秦怀杂货店
发布于 2022-02-17 00:37:28
发布于 2022-02-17 00:37:28
46900
代码可运行
举报
文章被收录于专栏:技术杂货店技术杂货店
运行总次数:0
代码可运行

Part0前言

剑指Offer & LeetCode刷题仓库https://github.com/Damaer/CodeSolution 文档地址https://damaer.github.io/CodeSolution/ 刷题仓库介绍刷题仓库:CodeSolution 编程知识库https://github.com/Damaer/Coding 文档地址https://damaer.github.io/Coding/#/

想要了解数据结构全貌可以查看:万字长文带你漫游数据结构世界

Part168.二叉搜索树的最近公共祖先

1题目描述

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

  • 1.对于该题的最近的公共祖先定义:对于有根树T的两个结点pq,最近公共祖先LCA(T,p,q)表示一个结点x,满足xpq的祖先且x的深度尽可能大。在这里,一个节点也可以是它自己的祖先.
  • 2.二叉搜索树是若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值
  • 3.所有节点的值都是唯一的。
  • 4.pq 为不同节点且均存在于给定的二叉搜索树中。

如果给定以下搜索二叉树: {7,1,12,0,4,11,14,#,#,3,5},如下图:

示例 1

代码语言:javascript
代码运行次数:0
复制
输入: {7,1,12,0,4,11,14,#,#,3,5},1,12

输出: 7

说明:
节点1 和 节点12的最近公共祖先是7

示例 2

代码语言:javascript
代码运行次数:0
复制
输入: {7,1,12,0,4,11,14,#,#,3,5},12,11

输出: 12

说明:因为一个节点也可以是它自己的祖先.所以输出12

2思路 & 解答

何为二叉树?

二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉排序树。

也就是像下面这个:

题目已经保证了,两个节点 p,q 都在树上,我们取出根节点 7 ,假设小于 7 ,则在左子树,如果大于 7 ,则在右子树。

那么需要查找的两个节点,但凡有一个等于根节点,它们的父节点就是根节点,因为一个节点的父节点可以是自身(题目有说明)。

如果一个大于根节点,一个小于根节点,其最近公共祖先也是根节点。

如果两个都大于,或者两个都小于,怎么办?

当然是递归,如果两个都小于,那么就取当前的左子树进行递归,直到符合要求。比如查找,3 和 5,由于 3 和 5 都小于 7,那么取左子树 1 下面的进行递归:

Java 代码如下:

代码语言:javascript
代码运行次数:0
复制
class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;
    }
}

public class Solution68 {

    public int lowestCommonAncestor(TreeNode root, int p, int q) {
        TreeNode result = commonAncestor(root, p, q);
        return result == null ? -1 : result.val;
    }

    public TreeNode commonAncestor(TreeNode root, int p, int q) {
        // 等于空
        if (root == null) {
            return null;
        }
        if (root.val == p || root.val == q) {
            // 有一个值等于根节点
            return root;
        }
        // 在左子树
        if (p < root.val && q < root.val) {
            return commonAncestor(root.left, p, q);
        } else if (p > root.val && q > root.val) {
            // 两个都在右子树
            return commonAncestor(root.right, p, q);
        } else {
            return root;
        }
    }
}

C++ 代码如下:

代码语言:javascript
代码运行次数:0
复制
/**
 * struct TreeNode {
 * int val;
 * struct TreeNode *left;
 * struct TreeNode *right;
 * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
class Solution {
public:
    int lowestCommonAncestor(TreeNode *root, int p, int q) {
        TreeNode *result = commonAncestor(root, p, q);
        return result == NULL ? -1 : result->val;
    }


    TreeNode *commonAncestor(TreeNode *root, int p, int q) {
        // 等于空
        if (root == NULL) {
            return NULL;
        }
        if (root->val == p || root->val == q) {
            // 有一个值等于根节点
            return root;
        }
        // 在左子树
        if (p < root->val && q < root->val) {
            return commonAncestor(root->left, p, q);
        } else if (p > root->val && q > root->val) {
            // 两个都在右子树
            return commonAncestor(root->right, p, q);
        } else {
            return root;
        }
    }
};

假设这道题条件改一下,如果不是二叉搜索树,怎么办?

如果不是二叉搜索树,那么我们不能直接判断出它在左子树,还是在右子树。不如暴力点,先在左子树中找,如果右子树没找到,说明都在左子树,如果左子树没找到,说明都在右子树,如果两个都分别存在,说明当前节点就是他们的父节点。

Java 代码如下:

代码语言:javascript
代码运行次数:0
复制
public class Solution68 {

    public int lowestCommonAncestor(TreeNode root, int p, int q) {
        TreeNode result = commonAncestor(root, p, q);
        return result == null ? -1 : result.val;
    }

    public TreeNode commonAncestor(TreeNode root, int p, int q) {
        if (null == root) {
            return null;
        }
        if (root.val == p || root.val == q) {
            return root;
        }
        TreeNode left = commonAncestor(root.left, p, q);
        TreeNode right = commonAncestor(root.right, p, q);
        if (left == null) {
            return right;
        } else if (right == null) {
            return left;
        } else {
            return root;
        }
    }
}

C++ 代码如下:

代码语言:javascript
代码运行次数:0
复制
/**
 * struct TreeNode {
 * int val;
 * struct TreeNode *left;
 * struct TreeNode *right;
 * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
class Solution {
public:
    int lowestCommonAncestor(TreeNode *root, int p, int q) {
        TreeNode *result = commonAncestor(root, p, q);
        return result == NULL ? -1 : result->val;
    }


    TreeNode *commonAncestor(TreeNode *root, int p, int q) {
        // 等于空
        if (root == NULL) {
            return NULL;
        }
        if (root->val == p || root->val == q) {
            // 有一个值等于根节点
            return root;
        }
        TreeNode* left = commonAncestor(root->left, p, q);
        TreeNode* right = commonAncestor(root->right, p, q);
        if (left == NULL) {
            return right;
        } else if (right == NULL) {
            return left;
        } else {
            return root;
        }
    }
};

【作者简介】

秦怀,技术之路不在一时,山高水长,纵使缓慢,驰而不息。个人网站:http://aphysia.cn ,关注我,我们一起成长吧~

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-01-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 秦怀杂货店 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【leetcode刷题】T131-二叉搜索树的最近公共祖先
https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-search-tree/
木又AI帮
2019/08/02
4160
golang刷leetcode 二叉树(10)最近公共祖先
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
golangLeetcode
2022/08/02
2180
golang刷leetcode 二叉树(10)最近公共祖先
二叉搜索树的公共祖先问题!
题目链接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-search-tree/
代码随想录
2021/09/08
3520
二叉搜索树的公共祖先问题!
二叉搜索树的最近公共祖先
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
木子星兮
2020/07/17
4360
leetcode刷题(45)——35. 二叉搜索树的最近公共祖先
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
老马的编程之旅
2022/06/23
1570
leetcode刷题(45)——35. 二叉搜索树的最近公共祖先
图解LeetCode——剑指 Offer 68 - I. 二叉搜索树的最近公共祖先
根据题目描述,我们给我们两个节点TreeNode p和TreeNode q,然后在二叉搜索树中去寻找最近公共祖先。那么题目中给出了非常关键的一个信息就是——二叉搜索树,那么这种二叉树具有如下的特征:
爪哇缪斯
2023/05/10
1620
图解LeetCode——剑指 Offer 68 - I. 二叉搜索树的最近公共祖先
二叉树的最近公共祖先
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
初阶牛
2023/10/14
2230
二叉树的最近公共祖先
腾讯精选50题算法【二叉搜索树的最近公共祖先】
最近几周掺杂着需求、以及一些琐碎的事情,算法的学习一直都是默默的在搞,没有形成文章。
程序员小跃
2019/12/25
7360
​LeetCode刷题实战235:二叉搜索树的最近公共祖先
算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !
程序员小猿
2021/04/15
2940
【剑指Offer】68.1 二叉搜索树的最近公共祖先
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
瑞新
2020/12/07
2640
【剑指Offer】68.1 二叉搜索树的最近公共祖先
二叉树的最近公共祖先
这道题目的看代码比较简单,而且好像也挺好理解的,但是如果把每一个细节理解到位,还是不容易的。
代码随想录
2021/09/08
2.6K0
二叉树的最近公共祖先
二叉树子节点的最近父节点
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
conanma
2021/06/08
1.8K0
【二叉树进阶】二叉树经典面试题——最近公共祖先问题
7和4呢,2 、5 、3是不是都是它们两个的公共祖先啊,但是题目要求找最近的公共祖先,所以是2。 再看一种情况
YIN_尹
2024/01/23
1420
【二叉树进阶】二叉树经典面试题——最近公共祖先问题
【一天一大 lee】二叉搜索树的最近公共祖先 (难度:简单) - Day2020092
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
前端小书童
2020/09/30
3270
【一天一大 lee】二叉搜索树的最近公共祖先 (难度:简单) - Day2020092
[第33期] 树,二叉树, 二叉搜索树
比如想想访问中间某个结点的时候,或者倒数第几个结点 就只能从头往后一个一个查, 效率不高。
皮小蛋
2020/02/29
5260
一文秒杀 5 道最近公共祖先问题
读完本文,可以去力扣解决如下题目: 236. 二叉树的最近公共祖先(中等) 1644. 二叉树的最近公共祖先 II(中等) 1650. 二叉树的最近公共祖先 III(中等) 1676. 二叉树的最近公共祖先 IV(中等) 235. 二叉搜索树的最近公共祖先(简单) 如果说笔试的时候经常遇到各种动归回溯的骚操作,那么面试会倾向于一些比较经典的问题,难度不算大,而且也比较实用。 本文就用 Git 引出一个经典的算法问题:最近公共祖先(Lowest Common Ancestor,简称 LCA)。 git pull 这个命令我们经常会用,它默认是使用 merge 方式将远端别人的修改拉到本地;如果带上参数 git pull -r,就会使用 rebase 的方式将远端修改拉到本地。 这二者最直观的区别就是:merge 方式合并的分支会看到很多「分叉」,而 rebase 方式合并的分支就是一条直线。但无论哪种方式,如果存在冲突,Git 都会检测出来并让你手动解决冲突。 那么问题来了,Git 是如何合并两条分支并检测冲突的呢? 以 rebase 命令为例,比如下图的情况,我站在 dev 分支执行 git rebase master,然后 dev 就会接到 master 分支之上:
labuladong
2022/03/31
1.7K1
一文秒杀 5 道最近公共祖先问题
LeetCode 236:二叉树的最近公共祖先
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 输出:5 解释:节点 5 和节点 4 的最近公共祖先是节点 5 。因为根据定义最近公共祖先节点可以为节点本身。
Wu_Candy
2022/07/04
3070
LeetCode 236:二叉树的最近公共祖先
【leetcode刷题】T132-二叉树的最近公共祖先
https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/
木又AI帮
2019/08/06
3610
二叉树OJ题(C++实现)
主要思路是借助一个队列,将每一层的数据以size统计,当size为0时说明该层数据已经输入完,将这一层的数据传入vector中,再通过push_back 传入 vector< vector< int >中
lovevivi
2023/10/16
1870
二叉树OJ题(C++实现)
LeetCode 二叉树的最近公共祖先(二叉树)
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
SakuraTears
2022/01/13
2000
LeetCode 二叉树的最近公共祖先(二叉树)
推荐阅读
相关推荐
【leetcode刷题】T131-二叉搜索树的最近公共祖先
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文