基于深度的LCA算法: 对于两个结点u、v,它们的深度分别为depth(u)、depth(v),对于其公共祖先w,深度为depth(w),u需要向上回溯depth(u)-depth(w)步,v需要depth(v)-depth(w)步。 因此,只需要u,v中深度较大的向上移,直到 depth(u)=depth(v) && 此时指向一个结点。
因此,求出LCA的时间复杂度为O(depth(u)+depth(v)); 求深度,只需要进行一次遍历,O(n)。
如果是完全二叉树的话,相当于深度(下标)已经建立好了,直接根据LCA进行计算。
1 vector<int> G[MAXV]; // 树 2 int root; 3 4 int parent[MAXV]; // 父节点; (并查集) 5 int depth[MAXV]; // 节点深度 6 7 // v:当前结点 p:父节点 d:深度 8 void DFS(int v,int p,int d){ 9 parent[v]=p; 10 depth[v]=d; 11 for(auto& p:G[v]){ 12 dfs(p,v,d+1); 13 } 14 } 15 16 void init(){ 17 dfs(root,-1,1); 18 } 19 20 int LCA(int u,int v){ 21 while(depth[u]>depth[v]){ 22 u=parent[u]; 23 } 24 while(depth[u]<depth[v]){ 25 v=parent[v]; 26 } 27 while(u!=v){ 28 u=parent[u]; 29 v=parent[v]; 30 } 31 return u; 32 }
如果需要查找多对LCA,可以考虑二分查找的性质,来找到最小步数。