01 看题和准备

今天介绍的是LeetCode算法题中Easy级别的第78题(顺位题号是371)。计算两个整数a和b的总和,但不允许使用运算符+和 - 。例如:

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

输入:a = -2,b = 3
输出:1

本次解题使用的开发工具是eclipse,jdk使用的版本是1.8,环境是win7 64位系统,使用Java语言编写和测试。

02 第一种解法

借助循环来实现。先将a赋值给临时变量sum,然后判断b的正负,如果b大于0,sum就自加加,同时b自减减;反之如果b小于0,则sum就自减减,b就自加加,最后返回sum即可。

public int getSum(int a, int b) {
    if (a == 0) {
        return b;
    }
    if (b == 0) {
        return a;
    }
    int sum = a;
    if (b > 0) {
        while (b > 0) {
            sum++;
            b--;
        }
    } else {
        while (b < 0) {
            sum--;
            b++;
        }
    }
    return sum;
}


03 第二种解法

因为题目说不许用加减运算符,所以我们需要考虑使用位运算。在做加法运算时,会产生进位的情况。先来看一个53+69例子:

  • 如果不考虑进位做加法,可以得到12。
  • 如果考虑进位做加法,可以得到110。

这时我们把两数12和110加起来,就是53和69的和,122。

如果把这种考虑位、不考虑位的计算方式换成二进制数,那么:

  • 如果不考虑进位做加法,0+0=0,1+0=1,0+1=1,1+1=0。这其实就是异或(^)运算,对应位不同时,取1,否则取0。
  • 如果考虑进位做加法,0+0=0,1+0=0,0+1=0,1+1=1。这其实就是与(&)运算,相同位均为1才是1。

首先,我们可以使用a和b之间的与(&)运算来查找进位。其次,我们可以在a和b之间使用异或(^)运算来查找不同的位,并将其赋值给a,然后,我们将进位向左移动一个位置并将其赋值给b,直到没有进位或b为0。最后返回a即可。

public int getSum2(int a, int b) {
    if (a == 0) {
        return b;
    }
    if (b == 0) {
        return a;
    }
    while (b != 0) {
        int carry = a&b;
        a = a^b;
        b = carry << 1;
    }
    return a;
}


04 第三种解法

我们可以将第二种解法变成递归的写法。

public int getSum3(int a, int b) {
    if (b == 0) {
        return a;
    }
    return getSum3(a ^ b, (a&b) << 1);
}