[01] 两整数之和

题目

给你两个整数 a 和 b ,不使用 运算符 + 和 - ​​​​​​​,计算并返回两整数之和。

示例 1:

输入:a = 1, b = 2
输出:3
示例 2:

输入:a = 2, b = 3
输出:5

提示:

-1000 <= a, b <= 1000

来源:力扣(LeetCode)
链接: link.

题解思路

利用位运算来解决

魔鬼细节

细节一

a ^ b 表示无进位的求和部分
(a & b) << 1 表示只保留进位部分
所以可以用两部分加起来代替加法,但是不能用"+"实现,转用循环或递归,直到进位 (a & b) << 1 为 0 为止

解析

位运算: & | ^

二进制中: ① 1 + 1 = 10 用 (1 & 1) << 1 or (1 | 1) << 1;
② 1 + 0 = 1 用 1 | 0 or 1 ^ 0
③ 0 + 0 = 0 用 0 & 0 or 0 | 0 or 0 ^ 0

从这里发现 a | b 、 a ^ b 除了不能实现进位,其他都能实现,
但是 a | b 在①中会产生一个小尾巴 1,而 a ^ b 则不会,所以表示无进位的求和
又因为 0 & 上任何数都是 0,所以 (a & b) << 1 才能表示单纯地进位,而 (a | b) << 1 就不行

细节二

用循环或递归,直到进位 (a & b) << 1 为 0 为止

解析

(a & b) << 1 表示的是进位部分,那么随着不断拆分,这部分会变成 0 ,此时 a ^ b 部分就真正表示 a + b 的和了

细节三

可以使用无符号类型来防止溢出。

解析

在 C++ 的实现中,当我们赋给带符号类型一个超出它表示范围的值时,结果是 undefined;而当我们赋给无符号类型一个超出它表示范围的值时,结果是初始值对无符号类型表示数值总数取模的余数。

细节四

循环写法中,对于语句顺序要把握好

解析

如果先写 a = a ^ b,再写 temp = …,这样就把初始的 a 改变了

代码

循环写法
class Solution {
public:
    int getSum(int a, int b) {
        
        while (b) {
            unsigned int temp = (unsigned int)(a & b) << 1;
            a = a ^ b;
            b =temp;
        }

        return a;

    }
};
递归写法
class Solution {
public:
    int getSum(int a, int b) {

        if(!a) return b;
        int sum = a ^ b, carry = (unsigned int)(a & b) << 1;
        return getSum(carry, sum);    
     
    }
};

参考题解

官方循环参考
https://leetcode.cn/problems/sum-of-two-integers/solution/liang-zheng-shu-zhi-he-by-leetcode-solut-c1s3/

递归参考
https://leetcode.cn/problems/sum-of-two-integers/solution/liang-zheng-shu-zhi-he-wei-yun-suan-qing-7095/

思路参考
https://leetcode.cn/problems/sum-of-two-integers/solution/javashi-pin-jiang-jie-xi-lie-sum-of-two-integers-b/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是小白_鸭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值