[未完成][基础算法/讨论]关于二叉树最小公共祖先(LCA)

设二叉树节点数为n,寻求m对的最小公共祖先(保证点值存在且唯一)

 

一、对于只寻求一对的最小公共祖先(即寻求数m = 1):

这种可以直接采用简单的O(n)算法,设公共祖先为V,两点分别为O1与O2,规律如下:

  • 若V为O1与O2中一点,则另一个点处在V的其中一个左右子树中
  • 若V不为O1与O2,则O1与O2分布在V的两个不同子树中,且O1与O2分布在非最小公共祖先同一个子树

因此据此写出代码:

  1. 若节点为空,返回 nullptr;
  2. 若节点为O1或者O2,返回该值 Chird_Val;
  3. 递归遍历左右子树,并分别记录左右返回值 Chird_Val;
  4. 若左右子树都有非 nullptr返回值 Chird_Val,则返回该点值 Root_Val(说明该点为最小公共祖先);
  5. 若只有一个有非 nullptr返回值 Chird_Val,则返回该返回值 Chird_Val;
  6. 若左右子树都为 nullptr返回值,则返回 nullptr;

 

二、对于多寻求的最小公共祖先

这种如果采用上面的算法,则很明显时间复杂程度为O(mn),不太高效,以下分享两种算法,分别是离线与在线操作

I. Tarjan 离线算法

该算法也可以操作非二叉树图,时间复杂程度为O(n+m)

需要维护一个并查集(各节点不小于1,并查集初始化father[x] = x)。

对于二叉树来讲,设目前点为u,u的儿子节点为v,与u有关的查询节点为w,tarjan算法具体规则如下 

  1. for each(v): dfs(v)
  2. 使v与u融合(并查集,father[find(v)] = u,此时father[u] = u恒成立)
  3. for each(w)
  4. 若w被遍历过,则father[w]为u与w的最小公共祖先

证明:类似于一* 中的规律。

posted @ 2021-12-25 00:31  蒟蒻zExNocs  阅读(68)  评论(0)    收藏  举报