最近公共祖先

最近公共祖先

概念

给定一棵有n个节点的树,树中的两个节点u和v的最近公共祖先lca,有以下定义

(1)lca既是u的祖先,又是v的祖先

(2)lca是所有u和v的公共祖先中深度最深的祖先,也就是距离u和v最近的祖先

倍增法

先来看一下朴素方法,假设在如下图所示的树上寻找节点u和v的最近公共祖先,过程如图所示,需要走5步。

考虑用倍增法,如下图所示,每次走一大步,假设步幅从8开始尝试,走8步明显超过了节点u的深度,不可以,那么尝试减少一半,走4步是可行的,接着尝试走2步,发现此时2步还是多了,那么再减少一半,尝试走1步,刚好走到了lca上,此时只走了2次,可见倍增法大大减少了操作的次数,可以提高效率。

接下来讲一下具体的代码思路,

  1. 先把u和v放在同一深度上,所以我们需要一个数组记录u和v的深度,这里用depth[i]来表示节点i的深度,深度浅的不需要动,深度深的节点沿着树向上走,直到走到和深度浅的节点的深度相同。

    先判断一下哪个深度深,哪个深度浅,统一规定节点u的深度深。

    if(depth[u]<depth[v]) {
    		int temp = u;
    		u = v;
    		v = temp;
    	}
    

    然后让节点u沿着树向上跳,假设跳2的i次方步,我需要直到此时跳到了哪个节点上,所以再来一个数组 p a [ u ] [ i ] pa[u][i] pa[u][i]来记录节点u向上跳2的i次方次时对应的节点。从最大的步幅开始跳,如果跳多了就会导致depth[u] < depth[v]+(1<<i),此时就不跳了,否则就向上跳,那么u就变成了 p a [ u ] [ i ] pa[u][i] pa[u][i]。for循环结束后u和v统一到了同一高度。

    for(int i =max-1;i >= 0;i--) {
    		if(depth[u] >= depth[v]+(1<<i))
    			u = pa[u][i];
    	}
    

    此时如果u和v相等说明已经找到了最近公共祖先,否则要接着找。

    if(u == v) return u;
    
  2. u和v一起向上跳,直到u和v相等。这里也是先从最大的步幅开始跳,如果跳大了肯定是相等的,但是这不是最近公共祖先,所以就不跳,只有不相等的时候才会跳。

    for(int i =max-1;i >= 0;i--) {
    		if(pa[u][i] != pa[v][i]) {
    			u  =pa[u][i];
    			v = pa[v][i];
    		}
    	}
    
  3. 预处理数组depth和pa

    在求数组pa时可以利用前面已经求出来的数组来求,比如要求 p a [ u ] [ i ] pa[u][i] pa[u][i],也就是节点u走2的i次方步,可以分成两步,即节点u先走2的i-1次方步,然后再走2的i-1次方步,加起来就是 2 i − 1 + 2 i − 1 = 2 i 2^{i-1}+2^{i-1}=2^i 2i1+2i1=2i,也就是 p a [ p a [ u ] [ i − 1 ] ] [ i − 1 ] pa[pa[u][i-1]][i-1] pa[pa[u][i1]][i1]

    private static void dfs(int u, int fa) {
    	// TODO Auto-generated method stub
    	for(int i =1;i < max;i++) pa[u][i] = pa[pa[u][i-1]][i-1];
    	for(int e:map[u]) {
    		if(e!=fa) {
    			depth[e] = depth[u]+1;
    			pa[e][0]=u;
    			 dfs(e, u);
    		}
    	}
    }
    

    额外思考:不会跳过头吗?

    其实这里也是为什么要采用倍增的原因,我们都知道二进制可以表示任意的十进制数字,假设我要向上跳n次,在我选择步幅跳的时候,每次选择的都是2的i次幂,当选择过大时我就不跳,也相当于第i位填0,当选择恰当时我就跳,相当于第i位填1,比如最开始的例子里8我没有跳,4跳了,2没有跳,1跳了,一共跳了4+1次,写成二进制就是101,所以不会跳过头,并且如果要跳n步,通过倍增我可以正好跳n步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/358682.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux第38步_编译“正点原子移植好的uboot”

uboot的全称是Universal Boot Loader&#xff0c;uboot是一个遵循GPL协议的开源软件&#xff0c;uboot是一个裸机代码&#xff0c;可以看作是一个裸机综合例程。现在的 uboot 已经支持液晶屏、网络、USB等高级功能。 uboot官方的uboot源码是给所有的半导体厂商准备的。ST公司会…

CSS自适应分辨率 postcss-pxtorem(适用于 Vite)

前言 此篇是基于 Vite Vu3 项目的 CSS 自适应分辨率&#xff01; 如果想知道基于 Webpack Vue2 可移步 《CSS自适应分辨率 amfe-flexible 和 postcss-pxtorem&#xff08;适用于 Webpack&#xff09;》 项目对应的主要插件版本如下&#xff1a; "vite": "^4…

使用Win32API实现贪吃蛇小游戏

目录 C语言贪吃蛇项目 基本功能 需要的基础内容 Win32API 介绍 控制台程序部分指令 设置控制台窗口的长宽 设置控制台的名字 控制台在屏幕上的坐标位置结构体COORD 检索指定标准设备的句柄&#xff08;标准输入、标准输出或标准错误&#xff09; 光标信息结构体类型CONSOLE_CUR…

人人都可配置的大屏可视化

大屏主要是为了展示数据和酷炫的效果&#xff0c;布局大部分是9宫格&#xff0c;或者在9宫格上做的延伸&#xff0c;现在介绍下 泛积木-低代码 提供的大屏可视化配置。 首先查看效果展示 泛积木-低代码大屏展示。 创建页面之后&#xff0c;点击进入编辑页面&#xff0c;在可视…

电子液晶屏幕生产厂污废水处理需要哪些工艺设备

随着电子液晶屏幕行业的不断发展&#xff0c;污废水处理成为了一个重要的环保问题。为了达到合规性排放要求&#xff0c;并保护环境&#xff0c;厂家需要采取一系列工艺设备来处理污废水。 首先&#xff0c;常见的一种处理工艺是物理与化学处理。物理处理包括预处理与固液分离&…

Servlet过滤器个监听器

过滤器和监听器 过滤器 什么是过滤器 当浏览器向服务器发送请求的时候&#xff0c;过滤器可以将请求拦截下来&#xff0c;完成一些特殊的功能&#xff0c;比如&#xff1a;编码设置、权限校验、日志记录等。 过滤器执行流程 Filter实例 package com.by.servlet;import jav…

看过来:大龄程序员转行的18个方向

程序员35岁后&#xff0c;无人问津、被下岗&#xff0c;说到底还是中国互联网企业普遍短命和中国程序员新人不断涌现导致的&#xff0c;前者是岗位的缩减&#xff0c;后者是供应的增加&#xff0c;两者一叠加&#xff0c;35岁程序员就成了背锅侠。 大龄程序员和老医生一样都是非…

MySQL数据库基础合集

MySQL数据库基础合集 目录 MySQL数据库基础合集SQL关键字DDL关键字DML关键字DQL关键字DCL关键字约束关键字 SQL基础数据类型整数类型字符类型浮点类型时间类型 数据定义语言DDL1.查看数据库2.创建库3.删除库4.切换库5.创建表6.删除表7.查看表8.查看表属性9.插入列10.修改列11.设…

【MySQL】学习如何通过DQL进行数据库数据的条件查询

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-63IIm2s5sIhQfsfy {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

股票市场

&#xff08;一&#xff09;股票市场 顾名思义&#xff0c;就是买卖股票的场所。就是为了撮合想发展但缺钱的企业与有钱但想投资的投资者。 股票市场按照交易场所&#xff0c;可分为场内市场和场外市场&#xff1a; 场内市场是指证券交易所&#xff0c; 场外市场就是证券交易…

Java 学生管理系统

条件要求&#xff1a; 自己写的代码&#xff1a; public class Student{private String id;private String name;private int age;private String address;public Student() {}public Student(String id, String name, int age, String address) {this.id id;this.name name…

element ui组件 el-date-picker设置default-time的默认时间

default-time &#xff1a;选择日期后的默认时间值。 如未指定则默认时间值为 00:00:00 默认值修改 <el-form-item label"计划开始时间" style"width: 100%;" prop"planStartTime"><el-date-picker v-model"formData.planStart…

【论文解读】Collaboration Helps Camera Overtake LiDAR in 3D Detection

CoCa3D 摘要引言Collaborative Camera-Only 3D DetectionCollaborative depth estimationCollaborative detection feature learning 实验结论和局限 摘要 与基于 LiDAR 的检测系统相比&#xff0c;仅相机 3D 检测提供了一种经济的解决方案&#xff0c;具有简单的配置来定位 3…

【Linux】Linux环境基础开发工具使用

上篇博客我们学习了Linux权限相关知识&#xff0c;那么这节课我们来学习一下Linux环境基础开发工具使用吧~&#xff0c;主要包括yum、vim、gcc/g的使用&#xff0c;以及Linux项目自动化构建工具。 目录 Linux软件包管理器--yum yum是什么 yum相关操作 yum本地配置 Linux编…

程序员怎么写简历_写简历软件

你们在制作简历时&#xff0c;是不是基本只关注两件事&#xff1a;简历模板&#xff0c;还有基本信息的填写。 当你再次坐下来更新你的简历时&#xff0c;可能会发现自己不自觉地选择了那个“看起来最好看的模板”&#xff0c;填写基本信息&#xff0c;却没有深入思考如何使简历…

小程序样例5:简单登录界面

基本功能 1、头像选择、用户名、密码、昵称选择、性别、城市 2、确认注册跳转 我的页面。 3、其他注册方式跳转用户名 密码登录方式 4、清除 和 密码显示按钮&#xff1a; 5、用户名、密码合法性校验&#xff1a; 6、点击微信图标&#xff0c;调转回微信登录&#xff1a; 代码…

模糊神经网络控制器(MATLAB)

模糊神经网络控制器(Fuzzy Neural Network Controller)是将模糊控制和神经网络相结合的一类控制器。它综合了两者的优点,主要包括以下特点: 知识表达能力强。模糊系统的语言规则和神经网络的学习能力相结合,可以表示复杂的非线性映射关系。 自适应能力强。神经网络提供了在线学…

幻兽帕鲁服务器部署教程(超详细)

幻兽帕鲁服务器部署教程&#xff08;超详细&#xff09; 文章目录 幻兽帕鲁服务器部署教程&#xff08;超详细&#xff09;[TOC] 前言一、怎么部署属于自己的幻兽帕鲁服务器一、怎么登录游戏体验&#xff1f; 前言 在帕鲁的世界&#xff0c;你可以选择与神奇的生物「帕鲁」一同…

HCIA学习作业五

拓扑图&#xff1a; PC端 PC1>ipconfig PC2>ipconfig PC3>ipconfig PC4>ipconfig PC>ping PC1>ping 192.168.1.125 PC1>ping 192.168.1.254 PC1>ping 192.168.1.253 PC2>ping 192.168.1.125 PC2>ping 192.168.1.253 PC3>ping 192.168.1.126…

蓝桥杯备战——9.读写AT24C02

1.分析原理图 由上图我们可以看到AT24C02通过IIC与单片机进行通讯&#xff0c;由于A0,A1,A2都接地&#xff0c;所以器件地址为0XA0。 2.IIC通讯协议 比赛的时候会提供IIC驱动代码&#xff0c;我们不需要自己去写&#xff0c;我这里简单贴出一份&#xff1a; #include "i…