最近公共祖先

原题链接
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
题意:找最小公共祖先(离两个点最近的公共祖先)
把每个节点看成二进制数,以1为根的完全二叉树,每个节点的父节点的编号等于自己的编号除以2。二进制数除2 <=> 二进制数右移1位
解题思路:
用string读入16进制字符串,转化为二进制字符串,找到两个二进制字符串的最长前缀,将该前缀转化为16进制字符串即为答案

做题时进入的误区:找两个二进制字符串的最长前缀,为了方便,找了16进制的前缀。当2进制右移的位数%4 = 0 时是等价的,反之,二进制位的权值发生变化,4个二进制位对应的16进制为也要发生变化 如
二进制数 1111 对应16进制 f
右移一位 0111 对应16进制 7 != f

另外,通过本次,学了个2进制与16进制互转的模板(详情看代码)

#include <iostream>
#include <cstdio>

using namespace std;

string dx[] = {"0", "1", "10", "11", "100", "101", "110", "111", "1000", "1001",   //(首位)16进制转2进制
              "1010", "1011", "1100", "1101", "1110", "1111"};
string dy[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001",   //(非首位)16进制转2进制
              "1010", "1011", "1100", "1101", "1110", "1111"};
string dd[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", //2进制转16进制
              "a", "b", "c", "d", "e", "f"};


string s1, s2, b1, b2;

string to2 (string s) { //转2进制
    string res = "";
    for (int i = 0; i < s.size(); i ++) {   
        if (i == 0) {   //防止出现前导0
            if (s[i] >= '0' && s[i] <= '9') res += dx[s[i] - '0'];
            else res += dx[s[i] - 'a' + 10];
        }
        else {
            if (s[i] >= '0' && s[i] <= '9') res += dy[s[i] - '0'];
            else res += dy[s[i] - 'a' + 10];
        }
    }
    return res;
}

string tox(string s) {  //转16进制
    string res = "";
    for (int i = s.size() - 1; i >= 0; i -= 4) {
        int start = max(i - 3, 0);
        int t = 0;
        for (int j = start; j <= i; j ++)
            t = t * 2 + s[j] - '0';
        res = dd[t] + res;
    }
    return res;
}
int main() {
    int T, tem = 0;
    cin >> T;
    while (T --) {
        s1 = s2 = "";
        cin >> s1 >> s2;

        b1 = to2(s1), b2 = to2(s2);
        int it = 0;
        while (it < b1.size() && it < b2.size() && b1[it] == b2[it])    it ++;

        string res = b1.substr(0, it);
        res = tox(res);
        printf("Case #%d: %s\n\n", ++ tem, res.c_str());
    }
    return 0;

}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值