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

【算法】LCA的三种算法

【算法】LCA的三种算法

什么是LCA?

LCA(Least Common Ancestors),即最近公共祖先,是指在有根树中,找出某两个结点x和y最近的公共祖先。
三种算法

用三种算法可以求解LCA问题,分别为朴素算法、倍增算法和Tarjan算法。

朴素算法

倍增算法和Tarjan算法都在建立在朴素算法的思想下,因此,了解朴素算法的思想有助于更好的理解进阶算法。
朴素算法前置知识:邻接表,dfs。
假设我们要寻找某两个节点x和y的LCA,那么我们肯定是让深度更深的那个结点跳到另一个结点深度处,然后再让这两个结点一起向上跳,直到首次相遇。
光说可以有些抽象,举个例子,就以下面这张图中的树为例。
图中结点4先跳到结点3的位置,然后两个结点一起向上跳,随后跳到结点1处相遇,所以结点2和结点4的LCA为结点1。
也就是说,我们只要记录下每个结点的深度信息和祖先信息,就能通过逐个向上跳跃直至相遇来确定两个结点的LCA。
这便是LCA朴素算法的核心支撑所在,但是由于朴素算法每次跳跃一层,因此他的时间复杂度很差,尤其是当树退化为链的时候,那么如果我们让他跳跃多层,是不是可以更好更快的解决问题呢?答案是一定的,而接下来的倍增算法就是这个思想。

倍增算法

倍增算法前置知识:邻接表,DP&倍增,dfs。
倍增算法我们将会定义一个数组fa[i][j]表示结点i向上跳2j层所到的结点,从而实现了倍增跳跃,而且,通过有限的组合跳跃,我们到达任意结点处。例如向上5层,我们可以先向上跳跃22层之后,再向上跳跃2^0次方。同时,我们可以证明又fa[x][i] = fa[fa[x][i-1]][i-1],实质就是2^(i-1) + 2^(i-1) = 2^i.
同时,倍增LCA算法中还用到了贪心的思想,假如现在有两个结点x,y,假设x深度更大,则我们要尽可能地让x在不超过y的深度的前提下,尽可能地接近y,也就是跨的步子尽可能大!这样操作过后,结点x与结点y的深度就一定相同了。
相同之后,如果已经重合,直接return,如果没有,那么现在两个结点处于一个平行的位置。接下来我们让两个结点同时向上跳,也是能跳多大就跳多大,但是肯定是有限制的,就像上一步一样,这个限制就是只有在跳完之后他们结点不重合时才跳。这个地方有点绕,不要急,我们结合代码看一下。
点击查看代码

int lca(int u, int v) { if(depth[u] < depth[v]) swap(u, v); for(int i = MAXLOG - 1; i >= 0; i--) { if(depth[u] - (1 << i) >= depth[v]) { u = parent[u][i]; } } if(u == v) return u; // 注意看这里,这一步是平行之后的操作 for(int i = MAXLOG - 1; i >= 0; i--) { if(parent[u][i] != parent[v][i]) { u = parent[u][i]; v = parent[v][i]; } } return parent[u][0]; }

我们注意到,在平行之后,只要在parent[u][i] != parent[v][i]的前提下尽可能地大跨步就能保证跳到最近的公共祖先的前一个位置,这个位置上面一层,也就是2^0方层就是公共祖先,同时也是最近的公共祖先。

Tarjan算法

Tarjan算法前置知识:邻接表,并查集,dfs。
Tarjan巧妙地将并查集和dfs结合在一起,实现了将单次查询地时间复杂度降到了常数级别的离线算法!
具体步骤如下:

  1. 对于每个节点u,初始化u的祖先为u本身,并标记u为已访问。
  2. 对于每条边(u,v):
    /* 如果v未被访问,则对v进行深度优先搜索,并将v的祖先设置为u。
    /* 如果v已经被访问,那么u和v的最近公共祖先就是u的祖先和v的祖先的最小值。
  3. 在查询LCA问题时:
    /* 对于每个查询(q, u, v),其中q为查询编号,u和v分别为查询的两个节点:
    /* 如果(u,v)已经被访问过,那么查询结果为(u,v)的最近公共祖先。
    /* 如果(u,v)未被访问过,那么查询结果为(u,v)的最近公共祖先的祖先。
    总结

    离线用Tarjan,在线用倍增。:)

《网络安全从零到精通全套学习大礼包》

96节从入门到精通的全套视频教程免费领取

如果你也想通过学网络安全技术去帮助就业和转行,我可以把我自己亲自录制的96节 从零基础到精通的视频教程以及配套学习资料无偿分享给你。

网络安全学习路线图

想要学习 网络安全,作为新手一定要先按照路线图学习方向不对,努力白费。对于从来没有接触过网络安全的同学,我帮大家准备了从零基础到精通学习成长路线图以及学习规划。可以说是最科学最系统的学习路线,大家跟着这个路线图学习准没错。

配套实战项目/源码

所有视频教程所涉及的实战项目和项目源码

学习电子书籍

学习网络安全必看的书籍和文章的PDF,市面上网络安全书籍确实太多了,这些是我精选出来的

面试真题/经验

以上资料如何领取?

以上资料如何领取?


http://www.jsqmd.com/news/913377/

相关文章:

  • RTX-Tiny多版本库管理实践与Keil工程配置
  • 如何用Sherpa-Onnx构建完全离线的跨平台语音AI应用
  • 别再用老教程了!2024年Windows 11下配置DirectX SDK (June 2010) 的完整避坑指南
  • 35岁运维被优化后,我转了网络安全:这行的前景,比你想的更稳
  • 051、低分辨率图片放大后模糊?ESRGAN/SwinIR 超分辨率模型选型与边缘增强方案
  • 可靠是一切的前提!ROBOMIND的产品哲学
  • 2026年期货量化云主机部署:主流工具环境依赖与运维对照
  • MySQL数据库_教程(超详细)
  • 新手避坑指南:用Requests+BeautifulSoup爬取豆瓣电影Top250,解决反爬与数据清洗难题
  • 合规办学打底,构建闭环错题清零教学体系
  • 技术架构深度解析:ZLUDA如何实现跨平台CUDA兼容性
  • 量子模拟解析1T-TaS2电子弛豫的噪声辅助机制
  • 用Python+NumPy手把手模拟人寿保险健康状态预测(附完整代码)
  • 架构进阶:从 Docker 环境变量到 Nacos 统一配置中心实战
  • 第16篇 实战:用 Docker Compose 编排 WordPress 与 MySQL
  • 避坑指南:GSVA分析中你可能忽略的3个关键参数与数据预处理细节
  • 智慧政务大数据整体解决方案全解析|架构设计、建设内容、落地实践与价值复盘
  • AI搜索推广工具如何工程化落地:中科信枢龙虾智能体的内容资产与多平台分发架构
  • 手把手教你用Python+sklearn计算classification_report(附多分类不平衡数据集实战)
  • 【2024最严AI监管倒计时】:Claude风险评估矩阵4.2版紧急升级清单(含GDPR/CCPA/《生成式AI服务管理暂行办法》三重映射表)
  • 跨越操作系统壁垒:Linux下的BitLocker实时解密引擎
  • HarmonyOS 6.1 开发实战(一):如何做出高端精致的界面与交互
  • 为什么国产电源芯片越做越好,我却越来越焦虑?
  • 神经形态计算π²架构:突破AI硬件能效瓶颈
  • Lindy权限配置灾难频发?资深架构师紧急披露4类高危场景及实时熔断方案
  • 告别格式内耗!用 okbiye 格式排版,我把论文 “整容” 时间从 3 天砍到 5 分钟
  • 打造一款离线可用的桌面 OCR 工具:微信 OCR 引擎复用实践
  • 国产超宽带混频器打破垄断,水平国际先进,背后大有来头
  • AI看懂“弦外之音“:中科院软件所等机构联合攻克视频隐喻理解难题
  • 终末期心衰并非终局!合肥高心成功破局112kg超高危多病灶心衰患者