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

寻找二叉树中两个节点的最低公共祖先

在二叉树中寻找两个节点的最低公共祖先(Lowest Common Ancestor,LCA)是一个经典的问题。在这个问题中,最低公共祖先是指在二叉树中,两个节点的公共祖先中离它们最近的那个节点。

问题定义

给定一棵二叉树的根节点和两个节点 pq,要求找到这两个节点的最低公共祖先。

方法一:递归法

一种常见的解决方案是使用递归。基本思想是通过递归遍历二叉树,从根节点开始,寻找 pq 的位置。如果在某个节点下找到了 pq,那么这个节点就是它们的最低公共祖先。

代码示例(C++)
#include <iostream>
using namespace std;// 定义二叉树节点
struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};// 递归函数:寻找两个节点的最低公共祖先
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if (root == nullptr || root == p || root == q) {return root;}// 在左子树中查找TreeNode* left = lowestCommonAncestor(root->left, p, q);// 在右子树中查找TreeNode* right = lowestCommonAncestor(root->right, p, q);// 如果 p 和 q 分别在当前节点的左右子树中,则当前节点就是 LCAif (left != nullptr && right != nullptr) {return root;}// 否则,返回非空的那个子树return left != nullptr ? left : right;
}int main() {// 创建一个示例二叉树TreeNode* root = new TreeNode(3);root->left = new TreeNode(5);root->right = new TreeNode(1);root->left->left = new TreeNode(6);root->left->right = new TreeNode(2);root->right->left = new TreeNode(0);root->right->right = new TreeNode(8);root->left->right->left = new TreeNode(7);root->left->right->right = new TreeNode(4);TreeNode* p = root->left;         // Node 5TreeNode* q = root->left->right->right;  // Node 4TreeNode* lca = lowestCommonAncestor(root, p, q);if (lca != nullptr) {cout << "Lowest Common Ancestor: " << lca->val << endl;} else {cout << "Lowest Common Ancestor not found" << endl;}return 0;
}

代码解析

  1. 递归基准条件

    • 如果当前节点是 nullptr,或者当前节点是 pq,那么这个节点可能是 LCA(或者当前子树中没有公共祖先),因此直接返回当前节点。
  2. 递归搜索左右子树

    • 对当前节点的左右子树分别进行递归搜索,找到 pq 的位置。
  3. 确定 LCA

    • 如果 pq 分别位于左右子树中,则当前节点即为最低公共祖先。
    • 如果只在某一侧找到了 pq,则返回找到的那个节点。
  4. 返回结果

    • 如果递归最终找到某个节点是公共祖先,则返回该节点;否则返回 nullptr

时间和空间复杂度

  • 时间复杂度:O(N),其中 N 是二叉树中的节点数量。最坏情况下需要遍历所有节点。
  • 空间复杂度:O(H),其中 H 是二叉树的高度。递归调用栈的深度等于树的高度。

总结

通过递归的方法,可以非常高效地在二叉树中寻找两个节点的最低公共祖先。这种方法利用了二叉树的结构特点,避免了不必要的计算,非常适合处理常见的二叉树结构问题。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 2024小学生古诗文大会暑期备考:吃透历年真题和知识点(持续)
  • 简单的docker学习 第1章 docker 概述
  • springcloud loadbalancer nacos无损发布
  • 【数据结构】线段树
  • 临床数据科学中如何用R来进行缺失值的处理(上)
  • 24/8/6算法笔记 不同核函数
  • 读友好的缓存淘汰算法
  • Go语言依赖管理:如何配置和恢复Go模块镜像
  • 【python】Linux升级版本
  • python 装饰器记录函数用时
  • stm32应用、项目
  • RNN循环网络层
  • PostgreSQL(二十五)PG_FDW的使用
  • SpringMVC快速学习
  • C#裁剪图像的几种方法总结
  • 10个确保微服务与容器安全的最佳实践
  • ABAP的include关键字,Java的import, C的include和C4C ABSL 的import比较
  • Hexo+码云+git快速搭建免费的静态Blog
  • IOS评论框不贴底(ios12新bug)
  • java2019面试题北京
  • Terraform入门 - 3. 变更基础设施
  • 规范化安全开发 KOA 手脚架
  • 自动记录MySQL慢查询快照脚本
  • 东超科技获得千万级Pre-A轮融资,投资方为中科创星 ...
  • ​3ds Max插件CG MAGIC图形板块为您提升线条效率!
  • ​业务双活的数据切换思路设计(下)
  • #【QT 5 调试软件后,发布相关:软件生成exe文件 + 文件打包】
  • #我与Java虚拟机的故事#连载01:人在JVM,身不由己
  • (AngularJS)Angular 控制器之间通信初探
  • (CVPRW,2024)可学习的提示:遥感领域小样本语义分割
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (MTK)java文件添加简单接口并配置相应的SELinux avc 权限笔记2
  • (NO.00004)iOS实现打砖块游戏(九):游戏中小球与反弹棒的碰撞
  • (Redis使用系列) SpirngBoot中关于Redis的值的各种方式的存储与取出 三
  • (八)c52学习之旅-中断实验
  • (附源码)ssm跨平台教学系统 毕业设计 280843
  • (附源码)计算机毕业设计SSM基于java的云顶博客系统
  • (回溯) LeetCode 131. 分割回文串
  • (接口封装)
  • (十)c52学习之旅-定时器实验
  • (转)http协议
  • (转)Oracle 9i 数据库设计指引全集(1)
  • .gitignore文件_Git:.gitignore
  • .NET 5.0正式发布,有什么功能特性(翻译)
  • .NET Core 中的路径问题
  • .NET Core使用NPOI导出复杂,美观的Excel详解
  • .Net Remoting常用部署结构
  • .net 连接达梦数据库开发环境部署
  • .NET 同步与异步 之 原子操作和自旋锁(Interlocked、SpinLock)(九)
  • .Net程序帮助文档制作
  • .NET程序员迈向卓越的必由之路
  • .NET框架类在ASP.NET中的使用(2) ——QA
  • .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验
  • .so文件(linux系统)
  • .vimrc php,修改home目录下的.vimrc文件,vim配置php高亮显示