LeetCode 371: Sum of Two Integers 题解

来源:互联网 发布:php 端口号链接超时 编辑:程序博客网 时间:2024/04/28 02:11

原题如下:

LeetCode 371: Sum of Two Integers

Problem:
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.


题的意思是计算两个整数的和,但是不能用加号(+)和减号(-),当然也不能用:+=、-=、++、–了,既然不能用加减来做运算,那乘除运算能求两个数的和吗,显然是不能的,除非遇到两个数相等,或者其中一个等于0等特殊情况,但是这道题要求对任意两个数字求和,那么加减乘除都不能做到这一点,自然能想到只能通过位运算来达到目的了。

首先,有关的运算包括:按位与(&)、按位或(|)、按位异或(^)、移位。那么要如何用这些运算计算两个数的和呢。下面来看个例子。

假设有两个数 a = 0010, b = 0011,我们可以知道:
1) a & b = 0010
2) a | b = 0011
3) a ^ b = 0001
其中与运算将对应的位均为1的位表示了出来(在这里是第2位),这就表示该位要进位,它的下一位(在这里是第三位)需要加上1。亦或将所有的对应位不相同的位表示了出来(在这里只有第一位),这就表示如果所有的位都没有进位的话,那么这个亦或的值就是答案,因为二进制的加法如果不考虑进位的话,就等价于两个二进制数相亦或。而或运算在这里的用处不大,因为加法的两个步骤:相加和进位已经分别被亦或运算和与运算实现了。那么现在来看看具体步骤:

首先,令 x=a & b = 0010 表示第三位需要加一;令 ans = a ^ b = 0001,表示不考虑进位的话,答案就为0001。我们先将 x 左移一位得到 x = 0100,表示第三位需要加上1。这时,令ans ^= x = 0101,得到一个没有考虑进位的答案,然后在来看看第一次进位之后还需不需要再进位:x &= ans = 0000,表示第一次进位之后就不需要进位了。那么 a+b = 0101。

要点就在于,与运算能够判断下一位是否需要加1,而亦或运算能够算出舍弃了进位的答案,那么如果循环执行这个流程,那么就能处理掉所有的进位。理解的最好办法就是再纸上多试试。

通过的代码如下:

int getSum(int a, int b) {    int shift = a & b;      //找出需要进位的位    int ans = a ^ b;        //得到不带进位的答案    while(shift){        shift <<= 1;        //将进位标志左移一位        int pre_ans = ans;  //记录之前的亦或值        ans ^= shift;       //得到新的不带进位的答案        shift &= pre_ans;   //找出还需要进位的位    }    return ans;}
0 0
原创粉丝点击