二叉搜索树中寻找最近公共祖先(LCA)的算法解析 | 高效解决方案

2025/3/15
本文详细介绍了如何在二叉搜索树(BST)中高效地找到两个节点的最近公共祖先(LCA),包括问题描述、解决思路、递归与迭代的代码实现、复杂度分析以及具体示例。
二叉搜索树结构图,显示节点6、2、8、0、4、7、9、3、5的层次关系

二叉搜索树(BST,Binary Search Tree)是一种特殊的二叉树,其中每个节点的左子树包含的值都小于该节点的值,右子树包含的值都大于该节点的值。在二叉搜索树中,寻找两个节点的最近公共祖先(LCA,Lowest Common Ancestor)可以利用二叉搜索树的性质来高效地解决。

问题描述

给定一个二叉搜索树和两个节点 pq,找到这两个节点的最近公共祖先。

解决思路

由于二叉搜索树的性质,我们可以利用以下规则来寻找最近公共祖先:

  1. 如果 pq 的值都小于当前节点的值,那么它们的最近公共祖先一定在当前节点的左子树中。
  2. 如果 pq 的值都大于当前节点的值,那么它们的最近公共祖先一定在当前节点的右子树中。
  3. 如果当前节点的值介于 pq 的值之间,或者当前节点的值等于 pq 的值,那么当前节点就是它们的最近公共祖先。

代码实现

以下是使用递归和迭代两种方式实现的代码示例:

递归实现

function lowestCommonAncestor(root, p, q) {
    if (root.val > p.val && root.val > q.val) {
        return lowestCommonAncestor(root.left, p, q);
    } else if (root.val < p.val && root.val < q.val) {
        return lowestCommonAncestor(root.right, p, q);
    } else {
        return root;
    }
}

迭代实现

function lowestCommonAncestor(root, p, q) {
    while (root) {
        if (root.val > p.val && root.val > q.val) {
            root = root.left;
        } else if (root.val < p.val && root.val < q.val) {
            root = root.right;
        } else {
            return root;
        }
    }
    return null;
}

复杂度分析

  • 时间复杂度: O(h),其中 h 是树的高度。对于平衡的二叉搜索树,h = log(n),其中 n 是节点数。对于最坏情况(树退化为链表),h = n。
  • 空间复杂度:
    • 递归实现: O(h),递归栈的深度取决于树的高度。
    • 迭代实现: O(1),只使用了常数级别的额外空间。

示例

假设有如下二叉搜索树:

        6
       / \
      2   8
     / \ / \
    0 4 7 9
      / \
     3 5
  • 节点 28 的最近公共祖先是 6
  • 节点 24 的最近公共祖先是 2
  • 节点 35 的最近公共祖先是 4

总结

利用二叉搜索树的性质,我们可以高效地找到两个节点的最近公共祖先。无论是递归还是迭代实现,时间复杂度都是 O(h),其中 h 是树的高度。在实际应用中,迭代实现通常更为高效,因为它避免了递归调用的开销。

标签:算法
上次更新:

相关文章

FFmpeg 安装教程:Linux/Windows/macOS/Docker 全指南

本指南详细介绍在不同操作系统(Ubuntu/Debian、CentOS/RHEL、Windows、macOS)和 Docker 环境中安装 FFmpeg 的完整步骤,包括命令示例和验证方法。

·后端开发

Node-Cache 完全指南 | Node.js 内存缓存模块使用教程

本文详细介绍了 Node-Cache 模块,这是一个简单高效的 Node.js 内存缓存解决方案,包括安装方法、基本使用、主要功能、高级特性、配置选项以及实际应用场景。

·前端开发

npx完全指南:前端开发必备工具详解 | 20年架构师深度解析

本文由20年前端架构师深入解析npx工具,涵盖其核心功能、优势、高级用法、最佳实践及与npm/yarn的区别比较,帮助开发者掌握这一现代前端开发利器。

·前端开发

<处理关联数据的最佳实践:Article 与 Tags 的关系 | 开发指南>

<本文详细介绍了在开发中处理关联数据(如 Article 和 Tags 的多对多关系)的最佳实践,包括拆分业务逻辑、使用事务保证数据一致性、合理设计关联表结构、批量操作、幂等性和乐观锁等关键要点,并提供了基于 mysql2 和 Sequelize 的代码示例。>

·后端开发

Astro 静态站点生成器:构建高性能网站的最佳选择

Astro 是一个专注于构建快速、轻量级网站的静态站点生成器,支持多种前端框架,采用岛屿架构减少 JavaScript 加载,提升性能。

·前端开发

MySQL外键约束详解:维护数据一致性与完整性

本文详细介绍了MySQL中的外键约束(Foreign Key Constraint),包括其基本概念、创建方法、作用、级联操作、限制、修改与删除方法、查看方式以及最佳实践。通过合理使用外键约束,可以有效管理数据库中的数据关系,确保数据的准确性和可靠性。

·后端开发

MySQL JSON数据类型支持与使用指南 | 详细解析与示例

本文详细解析了MySQL从5.7版本开始支持的JSON数据类型,包括版本支持、创建JSON字段、插入与查询JSON数据、修改JSON数据、生成JSON、索引优化、性能与应用场景、注意事项及示例全流程。

·后端开发

SQL JOIN、LEFT JOIN 和 RIGHT JOIN 的区别与应用场景详解

本文详细介绍了 SQL 中 JOIN、LEFT JOIN 和 RIGHT JOIN 的区别,包括它们的作用、语法、示例以及实际应用场景,帮助读者更好地理解和使用这些连接方式。

·后端开发

Weex 跨平台移动开发框架:核心特性与使用指南

Weex 是由阿里巴巴开源的跨平台移动开发框架,支持使用 Vue.js 或 Rax 构建高性能的 iOS、Android 和 Web 应用。本文详细解析了 Weex 的核心特性、架构、工作流程、组件和模块、开发工具、优缺点、应用场景及未来发展。

·前端开发

ECharts 与 DataV 数据可视化工具对比分析 | 选择指南

本文详细对比了 ECharts 和 DataV 两个常用的数据可视化工具,包括它们的设计目标、优缺点、使用场景和技术栈,帮助读者根据具体需求选择合适的工具。

·前端开发