题解330. 二进制反码转换问题 | 豆包MarsCode AI刷题

43 阅读3分钟

题意简述

小C最近在学习二进制运算,他发现每个非负整数都有其独特的二进制表示。比如,整数 5 可以用二进制表示为 "101",而整数 11 则表现为 "1011"。值得注意的是,除了 N = 0 的情况外,任何非负整数的二进制表示都不应该有前导零,这一点非常重要。

在这个过程中,小C还接触到了反码的概念。二进制的反码表示是指将每一个 1 变为 0,每一个 0 变为 1。例如,数值 5 的二进制表示为 "101",那么它的反码就是 "010"。小C对这个概念产生了浓厚的兴趣,他想要计算一个给定十进制数 N 的二进制反码所对应的十进制数。

思路分析

这道题的核心在于计算某个非负整数 N 的二进制反码对应的十进制值。我们可以通过几个简单的步骤来完成这个计算。观察输入与输出之间的关系,我们发现它们的和加上 1 恰好是某个 2 的次方数。具体来说,假设 N 的二进制表示为 bkbk1...b1b0b_k b_{k-1} ... b_1 b_0,其中 k 表示最高位的索引。计算反码的过程可以分为以下几步:

  1. 确定位数:首先,我们需要确定 N 的二进制表示所占的位数。可以使用 N.bit_length() 来获取这个位数,这对于后续的计算至关重要。
  2. 计算补码:利用位数,我们可以计算出 2^m 的值,其中 m 是 N 的位数。补码的计算公式为 2^m - 1 - N。这里,2^m - 1 表示的是 m 位全为 1 的二进制数。
  3. 得到反码:反码则是补码减去 1,所以我们可以得到反码的公式为 2^m - 1 - N - 1,简化后即为 2^m - 2 - N
  4. 特殊情况处理:需要特别注意的是,当 N = 0 时,反码对应的十进制值为 1。这是因为在二进制中,0 被视为占用一位。

举个例子

为了更好地理解这一过程,我们可以通过一个具体的例子来说明,假设我们要计算 N = 5 的反码对应的十进制数。

  1. 确定位数:首先,将 5 转换为二进制,得到 "101"。我们可以看到,这个二进制数占用 3 位,因此 m = 3

  2. 计算补码

    • 首先计算 2^m 的值:2^3 = 8
    • 然后,计算补码:8 - 5。这里 8 - 5 得到的是 3,即二位二进制数 11,所以补码为 3
  3. 得到反码

    • 反码的计算公式是补码减去 13 - 1 = 2
  4. 确认结果:因此,N = 5 的反码对应的十进制数为 2。我们可以验证,5 的二进制反码是 "010",在十进制中对应的值是 2,所以最终答案是 3 - 1 = 2

代码

int solution(int N) {
    if (!N) {
        return 1;
    }
    int NN = N, n = 0;
    while (N) {
        n++;
        N >>= 1;
    }
    long long tmp = 1LL << n;
    return tmp - NN - 1;
}