编号满二叉树 - 寻找任意两结点的最近共同祖先

这是第一篇“技术性”博客,希望以后越写越多越好咯,本科生的期许hhh

以下是题目信息

《编号满二叉树 - 寻找任意两结点的最近共同祖先》

这道题运用的主要性质就是对于满二叉树任意结点编号i ,其parent(若有) 为 i/2

关键在于对算法的优化

Version 1.0

一开始只想把代码写出来,于是用了 < math.h >的pow函数,意图先算出两个结点的level,然后根据level 的差值将高位的结点“拉到”与地位的结点同一高度,然后再共同向上寻找祖先.

Version 2.0

V1的最大缺点(相对于v2)就是pow函数的使用使得代码复杂度变成了
O(1+2+…+level_a) + O(1+2+…+level_b) (毕竟pow执行了这么多次)
而显然可以通过记录一个数来使复杂度变为 O(1+2+…+level_bigger)
但仍然很慢,因为这种方法有这么几步

  1. 找到两个数的level
  2. 将较高的level降低到同一level(通过不断除以2)
  3. 不断同时除以2以找到共同结点(这是两个数会相同)

Version 3.0

然而V1,V2的方法还是蠢哭了。
通过观察:可以用辗转相除的方法(哪一个大就哪个除以2)来进行计算

while(a != b){
    if(a > b)
        a/=2;
    else b/= 2;
}

这样循环结束两个数都成为了共同祖先,而且时间复杂度大大降低

Version 4.0

然而故事还没结束

  • a /= 2; 可以通过位运算 改变为 a >>= 1;
  • cin、cout 可以通过改为scanf 和 printf 提升效率

    于是最终代码如下

#include <iostream>
using namespace std;

int main(){
int T;cin >> T;
for(int testcase = 0; testcase < T; ++testcase){

    int a,b; scanf("%d %d",&a,&b);
    while(a != b){
        if(a > b) a >>= 1;
        else b >>= 1;

    }
    printf("%d\n",a);
}
}

当然遗留了一些问题,这里做个小笔记

  • cin、cout 的具体实现
  • 乘除法的具体实现(我知道我上了数电…看来我还得去复习一下?)
  • 对上一条的延伸:浮点数乘除法的实现
    原文作者:满二叉树
    原文地址: https://blog.csdn.net/zys980808/article/details/78704163
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞