LeetCode*371. Sum of Two Integers

LeetCode题目链接

注意:凡是以英文出现的,都是题目提供的,包括答案代码里的前几行。

题目:

Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -.
Example:Given a = 1 and b = 2, return 3.
Credits:Special thanks to @fujiaozhu for adding this problem and creating all test cases.

希望看到这里的同学能够先思考,最好是能够自己写具体的实现,有更好的答案可以直接在下面评论。

解析:

既然规定不能用加减运算符,这个时候我们可以思考:计算机本身又是如何解决加法这个问题的呢?如果你听说过加法器这个东西,那么问题就比较好解决了。我们可以用逻辑运算来模拟加法。
首先,我们可以把十进制转化成二进制,我们需要一个具体的例子来分析。假设要计算12 + 29(1100 + 11101)的和。

|十进制\位数|5|4|3|2|1|
|-|-|-|-|-|
|12|0|1|1|0|0|
|29|1|1|1|0|1|

现在的问题就变成了怎么解决二进制加法的问题。由于加数和被加数的位数不定,又是在做加法,那么问题必然要用到循环。
两个位的和可以通过执行两个位的XOR(^)来获得。通过执行与(&)的两个位,可以获得进位。也就是半加法器逻辑。

语句 第一次循环
while(b != 0) { a = 01100, b = 11101 见上次 见上次 结束
int carry = a & b carry = 1100 carry = 10000 carry = 0
a = a ^ b a = 10001(17) a = 1001(9) a = 101001(41)
b = carry << 1 b = 11000(24) b = 100000(32) b = 0(0)
} 17 + 24 = 41 9 + 32 = 41 41 + 0 = 41

Q: 为什么是 carry << 1?

通过上面表格的分析,相信大家可以看到,每一列的 a + b 都等于 最终的结果。Why?这个算法本质上就是把有进位的无进位的分开加。a ^ b是计算无进位的和。a & b就是计算有进位的和。有进位的情况只有一种:两个相加的位同时为1,他们的和自然就是原来的2倍,也就是carry << 1。比如:1101(13) + 1101(13) = 11010(26)。

答案:

class Solution {
public:
    int getSum(int a, int b) {
        while (b != 0) {
            int carry = a & b;
            a = a ^ b;
            b = carry << 1;
        }
        return a;
    }
};

你可能感兴趣的:(LeetCode*371. Sum of Two Integers)