力扣1009补码解法C++实现

力扣 1009 题解析与 C++ 代码

一、问题解析

题目描述 :每个非负整数 N 都有其二进制表示。例如, 5 的二进制表示为 "101",其补码为 "010",即十进制中的 2。对于给定的十进制整数 N,返回其二进制表示取反(即补码)所对应的十进制整数。注意,二进制表示中不包含前导零,因此补码的二进制表示也不包含前导零。

核心要点

  1. 补码定义 :将原二进制数的每一位 0 变为 1 1 变为 0
  2. 无前导零 :计算补码时,只考虑原二进制数有效位的长度,忽略更高位的虚拟零。例如, 5 ( 101) 的有效位长度为3,其补码是 010 (即 2),而不是 ...11111010
  3. 数学等价关系 :对于一个有效位长度为 L 的二进制数 N,其补码等于 (2^L - 1) ^ N(2^L - 1) - N。其中 2^L1 是一个所有 L 位都为1的二进制掩码。

算法思路

  1. 确定有效位长度 :找到 N 的最高位 1 的位置,其索引(从0开始)加1即为长度 L
  2. 构造全1掩码 :创建一个二进制数,其低 L 位全为 1,高位全为 0。即 mask = (1 << L)1
  3. 计算补码 :将原数 N 与掩码 mask 进行按位异或 (^) 操作,即可得到补码。因为异或 1 会翻转该位。

时间复杂度 :O(1),因为整数位数固定(例如32位)。

空间复杂度:O(1)。

二、C++ 代码实现

方法一:位运算(异或掩码法)

这是最直接和高效的方法。

cpp 复制代码
class Solution {
public:
    int bitwiseComplement(int n) {
        // 处理边界情况:n为0时,其有效位长度为1,掩码为1,补码为1
        if (n == 0) return 1;

        // 步骤1:计算有效位长度 L
        int length = 0;
        int temp = n;
        while (temp > 0) {
            temp >>= 1; // 右移一位            length++;
        }
        // 或者使用内置函数: int length = floor(log2(n)) + 1;

        // 步骤2:构造全1掩码 mask = (1 << L)1
        int mask = (1 << length) - 1;

        // 步骤3:计算补码 n ^ mask return n ^ mask;
    }
};

方法二:位运算(循环取反法)

通过循环直接逐位翻转,逻辑更直观。

cpp 复制代码
class Solution {
public:
    int bitwiseComplement(int n) {
        if (n == 0) return 1;
        int result = 0;
        int bitPosition = 0; // 当前处理的位位置

        while (n > 0) {
            // 取n的最低位,并翻转 (0->1, 1->0)
            int currentBit = (n & 1) ^ 1;
            // 将翻转后的位放到结果的正确位置
            result |= (currentBit << bitPosition);
            // n右移一位,准备处理下一位
            n >>= 1;
            bitPosition++;
        }
        return result;
    }
};

方法三:利用 bitset(辅助理解)

使用标准库 bitset 可以更清晰地展示二进制操作过程,但效率略低。

cpp 复制代码
#include <bitset>
class Solution {
public:
    int bitwiseComplement(int n) {
        if (n == 0) return 1;
        // 确定需要的位数,32位足够 const int MAX_BITS = 32;
        std::bitset<MAX_BITS> bs(n);
        // 找到最高位1的位置
        int highestBit = MAX_BITS1;
        while (highestBit >= 0 && !bs.test(highestBit)) {
            highestBit--;
        }
        // 翻转从最高位到第0位的所有位 for (int i = 0; i <= highestBit; i++) {
            bs.flip(i);
        }
        // 转换回整数 return static_cast<int>(bs.to_ulong());
    }
};

三、算法对比

特性 异或掩码法 循环取反法 bitset 法
时间复杂度 O(log N) O(log N) O(log N)
空间复杂度 O(1) O(1) O(1)
核心思想 构造全1掩码后异或 逐位翻转并重组 使用标准库位集操作
代码简洁性 简洁 较简洁 直观但稍冗长
推荐度 推荐 推荐 适用于教学演示

四、关键点与示例

  1. 边界条件 :输入 N = 0 时,其二进制表示为 "0",有效长度视为1,补码为 "1",因此应返回 1
  2. 掩码构造(1 << L)1 是生成 L 位全1掩码的常用技巧。例如 L=3 1<<3 = 8 ( 1000), 8-1=7 ( 111)。
  3. 与 LeetCode 476 的关系 :本题 ( 1009) 与 `
  4. 数字的补数` 本质上是同一道题,解法完全相同。

测试示例

cpp 复制代码
int main() {
    Solution sol;
    cout << sol.bitwiseComplement(5) << endl; // 输出: 2 (101 -> 010)
    cout << sol.bitwiseComplement(7) << endl; // 输出: 0 (111 -> 000)
    cout << sol.bitwiseComplement(10) << endl; // 输出: 5 (1010 -> 0101)
    cout << sol.bitwiseComplement(0) << endl; // 输出: 1 (特殊处理)
    return 0;
}

参考来源

相关推荐
KaMeidebaby1 小时前
卡梅德生物技术快报|蛋白的叠氮基修饰:实操解析:核酸模板耦合蛋白的叠氮基修饰实现靶蛋白定点共价标记
前端·人工智能·物联网·算法·百度
2601_963645921 小时前
【2026最新】MATLAB教程(附安装包,非常详细)
开发语言·matlab·信息可视化
闲猫2 小时前
Python 虚拟环境 virtualenv & uvicorn 服务搭建 & FAstAPI 使用
开发语言·python
通信仿真爱好者2 小时前
第【60期】--大规模MIMO系统信号检测算法误码率比较 --matlab完整代码+参考文章
算法·matlab·mimo·信号检测
AI科技星3 小时前
全域谱分析:无穷维超复数信息场分形统一场论——自然、量子、金融多重分形第一性原理完整体系(中英双语终稿)
人工智能·python·算法·金融·乖乖数学·全域数学
三月不知肉味y3 小时前
2026-07-05-JAVA面试场景题训练
java·开发语言·面试
豆瓣鸡3 小时前
封装 API 请求日志切面——从注解定义到 Starter 自动装配
java·开发语言·spring boot
先吃饱再说4 小时前
为什么堆能 O(log n) 插入?拆解完全二叉树的数组魔法
算法·排序算法
留白_4 小时前
【决策树】泰坦尼克号生存预测
算法·决策树·机器学习