网站大量收购闲置独家精品文档,联系QQ:2885784924

43、最近公共祖先LCA查询.docx

  1. 1、本文档共6页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多

解题思路

问题分析

给定一棵树和两个节点,需要找到这两个节点的最低公共祖先。树上的最低公共祖先是一个经典的问题,如果我们能够在预处理中找到每个节点的所有祖先,那么在查询时就能够快速找到两个节点的最低公共祖先。

方法引入

我们可以使用“二进制提升”(BinaryLifting)技术来解决这个问题。这个方法的核心思想是预处理每个节点的所有祖先,以便在查询时快速找到两个节点的最低公共祖先。具体来说,对于每个节点,我们预先计算出它的第?20、21、22、...、2logN?个祖先。有了这些信息后,我们就可以在?logNlogN?的时间复杂度内找到任意两个节点的最低公共祖先。

实现过程

预处理:

使用DFS从根节点开始遍历整棵树,为每个节点计算其所有祖先。

使用数组parent[node][i]?来存储节点?node?的第?2^i个祖先。这样,parent[node][0]?就是节点?node?的直接父节点,parent[node][1]?是节点?node?的第?2?个祖先,依此类推。

当我们已经计算出了?parent[node][i]?和?parent[node][i?1]?时,我们可以使用关系?parent[node][i]=parent[parent[node][i?1]][i?1]?来计算?parent[node][i+1]。

查询:

为了找到两个节点?u和?v的最低公共祖先,首先确保?u?的深度不小于?v。

使用预处理的信息将?u?提升到与?v相同的深度。

如果提升后的?u?和?v相同,则两者就是它们的最低公共祖先。

否则,从最大的?ii?开始,尝试将?u和?v同时向上提升,直到它们有相同的第?2^i个祖先为止。

重复上述过程,直到找到?u和?v的最低公共祖先。

方法优劣分析

优点:

使用“二进制提升”技术,查询的时间复杂度为?logN。

预处理的时间复杂度为?NlogN,空间复杂度也为?NlogN。

缺点:

需要进行预处理,空间复杂度相对较高。

时间复杂度分析

预处理的时间复杂度为?O(NlogN)。

对于每个查询,时间复杂度为O(logN)。

总时间复杂度为O(NlogN+QlogN)=O((N+Q)logN)。

ACCode

C++

#includeiostream

#includevector

#includecmath

#includealgorithm

usingnamespacestd;

constintMAXN=1e5+5;

constintMAXLOG=20;//2^201e5

vectorinttree[MAXN];

intdepth[MAXN];

intparent[MAXN][MAXLOG];

voiddfs(intnode,intprev){

for(inti=1;iMAXLOG;i++){

parent[node][i]=parent[parent[node][i-1]][i-1];

}

for(intchild:tree[node]){

if(child!=prev){

depth[child]=depth[node]+1;

parent[child][0]=node;

dfs(child,node);

}

}

}

intlca(intu,intv){

if(depth[u]depth[v])swap(u,v);

for(inti=MAXLOG-1;i=0;i--){

if(depth[u]-(1i)=depth[v]){

u=parent[u][i];

}

}

if(u==v)returnu;

for(inti=MAXLOG-1;i=0;i--){

if(parent[u][i]!=parent[v][i]){

u=parent[u][i];

v=parent[v][i];

}

}

returnparent[u][0];

}

intmain(){

intN,Q;

cinN;

for(inti=1;iN;i++){

intu,v;

cinuv

文档评论(0)

如此醉 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档