算法37,位运算,两个整数之和(不用+符号)

题目

不使用 +-,计算两整数之和。

复制代码
输入: a = 1, b = 2    →  输出: 3
输入: a = 2, b = 3    →  输出: 5

代码

复制代码
class Solution {
    public int getSum(int a, int b) {
        while (b != 0) {
            int carry = (a & b) << 1;   // 进位
            a = a ^ b;                  // 无进位相加
            b = carry;
        }
        return a;
    }
}

核心思想:把加法拆成两半

十进制加法 15 + 27 你会拆成"个位相加"和"进位"两步。二进制也一样,而且拆分方式更干净

运算 作用 类比十进制
a ^ b 无进位相加(本位结果) 5+7 的个位是 2(不带进位)
(a & b) << 1 进位(哪几位要往前进) 5+7 满十进一

为什么是这两个式子?

  • ^ 是"不同为 1":1^1=0(1+1 本位写 0)、1^0=10^0=0 ------ 恰好就是不考虑进位时的加法结果
  • & 是"同为 1 才 1":只有 1&1 才产生进位,0 不会。但进位要加到高一位 ,所以 << 1

然后重复这个过程:把"无进位和"和"进位"再加一遍,直到进位为 0。

逐步演示 a = 5, b = 3(5+3=8)

复制代码
第1轮: a=0101  b=0011
       a^b     = 0110  (6)   ← 无进位和
       (a&b)<<1= 0010  (2)   ← 进位(第0位都是1,进到第1位)

第2轮: a=0110  b=0010
       a^b     = 0100  (4)
       (a&b)<<1= 0100  (4)   ← 第1位都是1,进到第2位

第3轮: a=0100  b=0100
       a^b     = 0000  (0)   ← 全撞上了,本位全写0
       (a&b)<<1= 1000  (8)   ← 进位到第3位

第4轮: a=0000  b=1000
       a^b     = 1000  (8)   ← 没有重叠了
       (a&b)<<1= 0000  (0)   ← 进位归零!

b = 0,循环结束 → 结果 8  ✓

关键:每一轮进位都往左移一位,所以低位会不断被 0 填满,最终进位被"挤"出 int 的 32 位范围,变成 0,循环必然终止。

实测覆盖(含负数)

a b 期望 位运算加法
1 2 3
2 3 5
-1 1 0
5 7 12
-3 -5 -8
0 0 0
-2 3 1
20 30 50

负数也完全没问题------因为 Java 用补码存储,加减法的二进制规则对有符号数同样成立,位运算不关心你怎么解释符号位。

两个值得记住的细节

① 循环为什么一定会停

每轮 b 都左移一位,最多 32 轮后所有进位都被挤出 int 范围,b 必然变成 0。所以最多循环 32 次,时间复杂度其实是 O(1)。

② 关于 >>> 的常见说法

很多题解会强调"必须用无符号右移 >>>"。但你这版代码用的是左移进位 + while (b != 0),实测负数用例全部正常 ------因为退出条件是 b == 0,不依赖右移来收敛。

需要注意 >>> 的是另一种写法(Python 模拟 32 位整数时常用右移来取模)。如果你的代码已经通过,说明这版写法在 Java 里是自洽的,不用改。

一句话总结

a ^ b 算出"不管进位的和",(a & b) << 1 算出"该进的位",把这俩再相加,反复到进位消失为止------这就是加法器的工作原理。

思维串联:这题把你笔记里的东西全串起来了------

  • ^ 异或:不同为 1 → 无进位加法
  • & 与:同为 1 才 1 → 找进位位置
  • << 左移:造掩码 / 把进位挪到高一位

延伸 :这题对应计算机组成原理里的半加器^ 是求和、& 是进位)和全加器 (多输入一个低位进位)。减法 a - b 同理可以写成 getSum(a, getSum(~b, 1))(即 a + (-b),而 -b = ~b + 1)。

相关推荐
猎头南楼1 小时前
MFC 质量流量控制器中的控制算法设计与落地思考
人工智能·算法
来一碗刘肉面1 小时前
平衡二叉树的删除
数据结构·算法
wabs6662 小时前
关于二叉树【力扣199.二叉树的右视图的思考】
数据结构·c++·算法·leetcode·二叉树·层序遍历
a187927218312 小时前
【算法】动态规划第三篇:背包第一课——贪心之死与正序倒序开关
算法·leetcode·动态规划·贪心·dp·暴力·算法讲解
黄金龙PLUS2 小时前
Xoodoo置换算法的优缺点
算法·网络安全·密码学·哈希算法·同态加密
LayZhangStrive2 小时前
数据结构与算法 - 堆排序
java·数据结构·算法·排序算法·堆排序·大根堆
residual_fan3 小时前
深度渐进收缩学习(DPSL):面向强噪声与类内分散的机械复合故障诊断方法
人工智能·算法·数据挖掘·数据分析
a187927218313 小时前
【算法】动态规划第五篇:区间 DP——从“看什么都像背包“到“最后戳谁“
算法·leetcode·动态规划·dp·区间·区间dp·算法讲解
whitelbwwww3 小时前
c++ 多线程
开发语言·c++·算法