当前位置: 首页 > news >正文

剑指Offer系列(java版,详细解析)68.树中两个节点的最低公共祖先

题目一

题目描述

剑指 Offer 68 - I. 二叉搜索树的最近公共祖先

难度简单122收藏分享切换为英文接收动态反馈

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

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]

img

示例 1:

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
输出: 6 
解释: 节点 2 和节点 8 的最近公共祖先是 6。

示例 2:

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
输出: 2
解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。

说明:

  • 所有节点的值都是唯一的。
  • p、q 为不同节点且均存在于给定的二叉搜索树中。

解题思路

明确一点即可:

二叉查找树中,两个节点 p, q 的公共祖先 root 满足 root.val >= p.val && root.val <= q.val。

自己解题

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        while(root != null) {
            if(root.val < p.val && root.val < q.val) // p,q 都在 root 的右子树中
                root = root.right; // 遍历至右子节点
            else if(root.val > p.val && root.val > q.val) // p,q 都在 root 的左子树中
                root = root.left; // 遍历至左子节点
            else break;
        }
        return root;
    }
}

题目二

题目描述

给定一棵普通树和两个节点,求这两个节点的最低公共祖先。在这棵树中的节点具有父节点的指针。

解题思路

这道题目就会退化为 两个链表的第一个公共节点 问题。

题目三

题目描述

给定一棵普通树和两个节点,求这两个节点的最低公共祖先。

解题思路

在左右子树中查找是否存在 p 或者 q,如果 p 和 q 分别在两个子树中,那么就说明根节点就是最低公共祖先。(但是要保证最低公共祖先)

为了避免重复查找,我们可以借助辅助空间保存从根节点到p和q的两条路径。
剩下的问题就是求这两条路径的最后一个公共节点。

参考解题

以二叉树为例:

/**
 * 普通树中两个节点的最低公共祖先
 */
public class Solution1 {
    /**
     * 求二叉树中两个节点的最低公共祖先
     *
     * @param root
     * @param p
     * @param q
     * @return
     */
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        // 防止特殊输入
        if (root == null || p == null || q == null) {
            return null;
        }
        ArrayList<TreeNode> pPath = new ArrayList<TreeNode>();
        ArrayList<TreeNode> qPath = new ArrayList<TreeNode>();
        // 寻找p、q路径
        findPath(root, p, pPath);
        findPath(root, q, qPath);
        // 寻找p、q路径的最后一个公共节点
        int minLength = Math.min(pPath.size(), qPath.size());
        int LCA = 0;
        for (int i = 0; i < minLength; i++) {
            if (pPath.get(i) == qPath.get(i)) {
                LCA = i;
            }
        }
        return pPath.get(LCA);

    }

    /**
     * 查找从根节点到目标节点的路径
     *
     * @param root
     * @param target
     * @param path
     * @return
     */
    public boolean findPath(TreeNode root, TreeNode target, List<TreeNode> path) {
        if (root == null) {
            return false;
        }
        path.add(root);
        if (root == target) {
            return true;
        }
        if (findPath(root.left, target, path) || findPath(root.right, target, path)) {
            return true;
        }
        path.remove(path.size() - 1);
        return false;
    }
}

相关文章:

  • Go语言fmt.Sprintf(格式化输出)
  • Go 面试系列:Go interface中nil的比较问题
  • Go 面试系列: new 和 make有什么不同之处呢?
  • Go 面试系列: Goroutine 数量是越多越好吗?设置多少会影响GC调度呢?
  • 什么是读、写扩散?
  • 一文搞定权限设计模型(RBAC,ABAC)超详细图文解析
  • 一文搞定权限管理!授权、鉴权超详细解析
  • Go 中的 JSON如何序列化和反序列化?来看看go的包怎么实现!
  • Go中如何比较两个json?深度优先搜索解决,超详细代码!
  • Go语言实现枚举方法,const和iota结合轻松实现
  • Go msgp序列化使用详解!比Json更快!面试时吊打面试官!
  • 缓存击穿了怎么办?使用singleflight轻松解决!
  • Go中优雅的获取Map元素的多种方法
  • Go中的nil是是什么?和java的null有区别吗?
  • 大厂面试必会语言:GO语言入门,看这一篇就够了
  • 2017 年终总结 —— 在路上
  • 230. Kth Smallest Element in a BST
  • 5、React组件事件详解
  • axios请求、和返回数据拦截,统一请求报错提示_012
  • docker python 配置
  • java第三方包学习之lombok
  • Java基本数据类型之Number
  • Java面向对象及其三大特征
  • Spring思维导图,让Spring不再难懂(mvc篇)
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • 程序员该如何有效的找工作?
  • 深度学习中的信息论知识详解
  • 学习HTTP相关知识笔记
  • ​水经微图Web1.5.0版即将上线
  • #include<初见C语言之指针(5)>
  • #前后端分离# 头条发布系统
  • #我与Java虚拟机的故事#连载01:人在JVM,身不由己
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (力扣)1314.矩阵区域和
  • (利用IDEA+Maven)定制属于自己的jar包
  • .net refrector
  • .NET 中各种混淆(Obfuscation)的含义、原理、实际效果和不同级别的差异(使用 SmartAssembly)
  • .net中的Queue和Stack
  • .one4-V-XXXXXXXX勒索病毒数据怎么处理|数据解密恢复
  • :O)修改linux硬件时间
  • @ 代码随想录算法训练营第8周(C语言)|Day53(动态规划)
  • @ConfigurationProperties注解对数据的自动封装
  • @transactional 方法执行完再commit_当@Transactional遇到@CacheEvict,你的代码是不是有bug!...
  • [1181]linux两台服务器之间传输文件和文件夹
  • [Angularjs]asp.net mvc+angularjs+web api单页应用
  • [C#小技巧]如何捕捉上升沿和下降沿
  • [CF]Codeforces Round #551 (Div. 2)
  • [Flutter] extends、implements、mixin和 abstract、extension的使用介绍说明
  • [IE技巧] 如何关闭Windows Server版IE的安全限制
  • [iOS开发]事件处理与响应者链
  • [javaee基础] 常见的javaweb笔试选择题含答案
  • [JavaScript]_[初级]_[关于forof或者for...of循环语句的用法]
  • [jQuery]使用jQuery.Validate进行客户端验证(中级篇-上)——不使用微软验证控件的理由...
  • [Linux]----文件操作(复习C语言+文件描述符)
  • [one_demo_5]命令行输入输出