LeetCode 1009. 十进制整数的反码(详细技术解析)

本文针对 LeetCode 1009. 十进制整数的反码 问题,提供完整的解题思路、代码实现及深度解析,帮助开发者理解问题本质、掌握解题技巧,同时规避常见误区。本题与 LeetCode 476. 数字的补数 完全一致,核心考点为二进制与十进制的转换、位运算的灵活应用,适合入门级位运算练习。

一、题目核心解读

1.1 题目描述(精简版)

给定一个非负整数 N,返回其二进制表示的反码所对应的十进制整数。

核心规则:

  • 二进制反码:将二进制表示中的每个 1 改为 0,每个 0 改为 1(注意:除 N=0 外,二进制无前置零,反码也无需保留前置零)。

  • 边界条件:0 ≤ N < 10⁹,覆盖常规整数范围,需考虑效率与边界处理。

1.2 示例解析(直观理解)

  • 示例 1:输入 5 → 二进制 "101" → 反码 "010" → 十进制 2(输出 2)。

  • 示例 2:输入 7 → 二进制 "111" → 反码 "000" → 十进制 0(输出 0)。

  • 示例 3:输入 10 → 二进制 "1010" → 反码 "0101" → 十进制 5(输出 5)。

关键观察:反码的本质是"对应位数的位翻转",但需注意 只翻转 N 二进制表示中有效位(非前置零),而非全部32位或64位(如 5 是3位二进制,仅翻转这3位,而非32位)。

二、解题思路深度剖析

解题核心:找到 N 二进制表示的"有效位数",构造一个与有效位数相同、全为1的二进制数(掩码),通过位运算中的"异或(^)"实现位翻转,最终得到反码对应的十进制数。

为什么用异或?异或运算规则:0 ^ 1 = 1,1 ^ 1 = 0,恰好实现"位翻转";而全1掩码可以确保只翻转有效位,不影响无效的前置零(前置零与1异或会变成1,但因有效位之外的前置零不参与十进制计算,可忽略)。

2.1 具体步骤(分3步)

  1. 处理边界 case:当 N = 0 时,二进制为 "0",反码为 "1",对应十进制 1(这是唯一需要单独处理的边界,因为其他数的有效位均≥1)。

  2. 计算 N 二进制的有效位数:例如 N=5(101),有效位数为3;N=10(1010),有效位数为4。

  3. 构造全1掩码:有效位数为 k,则掩码为 (1 << k) - 1(例如 k=3,1<<3=8,8-1=7,二进制 111;k=4,1<<4=16,16-1=15,二进制 1111)。

  4. N 与掩码异或,得到反码对应的十进制数(异或实现位翻转,掩码确保只翻转有效位)。

2.2 思路验证(结合示例)

示例 1:N=5(二进制 101)

  • 有效位数 k=3 → 掩码 = (1<<3)-1 = 7(111)

  • 5 ^ 7 = 101 ^ 111 = 010(二进制)→ 十进制 2(符合示例输出)

示例 2:N=7(二进制 111)

  • 有效位数 k=3 → 掩码=7(111)

  • 7 ^ 7 = 111 ^ 111 = 000(二进制)→ 十进制 0(符合示例输出)

示例 3:N=10(二进制 1010)

  • 有效位数 k=4 → 掩码=15(1111)

  • 10 ^ 15 = 1010 ^ 1111 = 0101(二进制)→ 十进制 5(符合示例输出)

2.3 常见误区提醒

  • 误区1:直接对 N 按位取反(~N)。错误原因:Python 中整数是无限位的,~N 会翻转所有位(包括前置的无限个0),导致结果为负数(如 ~5 = -6),不符合题目要求。

  • 误区2:忽略 N=0 的边界。N=0 二进制为 "0",反码为 "1",对应十进制 1,若不单独处理,会计算为 0 ^ 1 = 1(看似正确,但逻辑上需明确边界,避免后续扩展出错)。

  • 误区3:有效位数计算错误。例如 N=0 有效位数为1,N=1(1)有效位数为1,N=2(10)有效位数为2,需准确计算,否则掩码构造错误。

三、代码实现(Python)

按照题目要求,使用指定类和方法名,代码简洁高效,时间复杂度 O(logN)(计算有效位数的时间,与 N 的二进制位数成正比),空间复杂度 O(1)(无额外空间占用)。

python 复制代码
class Solution:
    def bitwiseComplement(self, N: int) -> int:
        # 处理边界 case:N=0 时,反码为1
        if N == 0:
            return 1
        # 计算 N 二进制的有效位数
        k = 0
        temp = N
        while temp > 0:
            k += 1
            temp = temp >> 1  # 右移1位,等价于 temp = temp // 2
        # 构造全1掩码:(1 << k) - 1
        mask = (1 << k) - 1
        # 异或运算实现位翻转,得到反码对应的十进制数
        return N ^ mask

四、代码逐行解析

4.1 边界处理

if N == 0: return 1

解释:当 N=0 时,二进制表示为 "0",反码为 "1",对应十进制 1,单独处理可避免后续逻辑对 0 的误判(若不处理,temp=N=0,循环不执行,k=0,mask=(1<<0)-1=0,0^0=0,错误)。

4.2 计算有效位数

python 复制代码
k = 0
temp = N
while temp > 0:
    k += 1
    temp = temp >> 1

解释:

  • 用 temp 临时存储 N,避免直接修改 N 的值。

  • 循环条件 temp > 0:当 temp 为 0 时,说明已遍历完所有有效位。

  • temp = temp >> 1:右移1位,等价于 temp = temp // 2,每次右移会丢弃最低位,直到 temp 变为 0,k 即为有效位数。

  • 示例:N=5(101),temp 初始为5 → 右移1位为2(10)→ 右移1位为1(1)→ 右移1位为0,循环执行3次,k=3。

4.3 构造全1掩码

mask = (1 << k) - 1

解释:

  • 1 << k:将 1 左移 k 位,得到一个 k+1 位的二进制数,最高位为1,其余为0(如 k=3,1<<3=8,二进制 1000)。

  • (1 << k) - 1:将左移后的数减1,得到 k 位全1的二进制数(如 8-1=7,二进制 111;k=4,16-1=15,二进制 1111),即我们需要的掩码。

4.4 异或运算实现位翻转

return N ^ mask

解释:异或运算的核心特性的是"相同为0,不同为1",恰好实现位翻转:

  • N 的二进制有效位与 mask(全1)异或,1→0,0→1,实现反码。

  • 有效位之外的前置零(若有)与 mask 的高位(0,因为 mask 只有 k 位全1)异或,仍为0,不影响结果。

五、性能优化与扩展

5.1 性能分析

  • 时间复杂度:O(logN)。N 的二进制位数为 log₂N + 1,循环执行次数等于二进制位数,因此时间复杂度与 logN 成正比。

  • 空间复杂度:O(1)。仅使用了 temp、k、mask 三个临时变量,与 N 的大小无关,空间开销固定。

适配题目约束(N < 10⁹):10⁹ 的二进制位数约为30位,循环最多执行30次,效率极高,无性能瓶颈。

5.2 代码简化(进阶写法)

利用 Python 内置函数 bin() 计算二进制位数,简化有效位数的计算,代码更简洁(本质与原代码逻辑一致):

python 复制代码
class Solution:
    def bitwiseComplement(self, N: int) -> int:
        if N == 0:
            return 1
        # bin(N) 得到 '0bxxxx',去掉前2位,长度即为有效位数
        k = len(bin(N)) - 2
        mask = (1 << k) - 1
        return N ^ mask

说明:bin(5) 得到 '0b101',len(bin(5))-2 = 3,与原方法计算的 k 一致,简化了循环逻辑,可读性更强。

5.3 扩展场景

若题目改为"翻转32位无符号整数的所有位",则无需计算有效位数,直接使用掩码 0xFFFFFFFF(32位全1),代码改为:

python 复制代码
class Solution:
    def bitwiseComplement(self, N: int) -> int:
        return N ^ 0xFFFFFFFF

但本题需注意"只翻转有效位",因此不能直接使用该方法,避免混淆场景。

六、总结与思考

6.1 核心知识点

  • 二进制与十进制的转换:理解整数的二进制表示,有效位的定义。

  • 位运算的应用:异或(^)实现位翻转,左移(<<)、右移(>>)构造掩码。

  • 边界处理:针对特殊值(如 N=0)的单独处理,避免逻辑漏洞。

6.2 解题启示

本题看似简单,但核心是"精准定位有效位",避免被位运算的表面用法迷惑(如直接取反)。解题时需先明确问题本质(只翻转有效位),再选择合适的位运算组合,同时重视边界 case 的处理,确保代码的健壮性。

对于类似的位运算题目(如数字的补数、二进制翻转等),核心思路均为"构造掩码 + 位运算",掌握这一思路可快速解决一类问题。

6.3 测试用例验证

补充3组测试用例,确保代码覆盖所有场景:

  • 测试用例4:N=0 → 输出 1(边界 case)。

  • 测试用例5:N=1 → 二进制 "1" → 反码 "0" → 输出 0。

  • 测试用例6:N=2 → 二进制 "10" → 反码 "01" → 输出 1。

将上述用例代入代码,均能得到正确结果,验证代码的正确性。

相关推荐
17(无规则自律)2 小时前
C++ 链表修炼指南
数据结构·c++·算法·leetcode·链表
z20348315202 小时前
17届蓝桥杯嵌入式赛道开发板外设使用教程——按键、蜂鸣器、LCD屏幕
mongodb·职场和发展·蓝桥杯
KhalilRuan2 小时前
基于OpenGL实现布料模拟
算法
大江东去浪淘尽千古风流人物2 小时前
【claw】 OpenClaw 的架构设计探索
深度学习·算法·3d·机器人·slam
闻缺陷则喜何志丹2 小时前
【字典树 回溯】P7210 [COCI 2020/2021 #3] Vlak|普及+
c++·算法·字典树·回溯·洛谷
夏玉林的学习之路2 小时前
委托构造和using关键字
开发语言·c++·算法
small-pudding2 小时前
深入理解PDF:蒙特卡洛光线追踪中的概率密度函数
算法·pdf·图形渲染
We་ct2 小时前
LeetCode 46. 全排列:深度解析+代码拆解
前端·数据结构·算法·leetcode·typescript·深度优先·回溯
逆境不可逃2 小时前
LeetCode 热题 100 之 763.划分字母区间
算法·leetcode·职场和发展
MicroTech20252 小时前
微算法科技(NASDAQ:MLGO)量子PBFT改进技术:重构联盟链共识的效率与安全
科技·算法·重构