[LintCode-Easy] A+B

原题:

Write a function that add two numbers A and B. You should not use + or any arithmetic operators.

给出两个整数a和b, 求他们的和, 但不能使用 + 等数学运算符。

(错误)解法1:

int aplusb(int a, int b) { // a and b are 32-bit integers
    int c = a | b, d = a & b;
    return c + d;
}
思路: 
  1. 把输入的两个int看成32位2进制数,则每一位两数全1的时候会发生进位,其他情况不会。
  2. 两数同一位全1的位可以通过与运算计算得出(‘&’运算结果为1的位即所求);其他情况的位的加法结果和或(‘|’)运算结果相同。
  3. 而两数同一位全1的时候或运算结果为1,和与运算结果相加,刚好进位,与实际求和结果效果相同

问题:虽然结果正确,但是函数体内仍然使用了‘+’,不符合要求。

解法2:

(递归-1)

int aplusb(int a, int b) { // recursive solution
        int xor_r = a ^ b;
        int and_r = a & b;
        if(and_r == 0) return xor_r;
        and_r = and_r << 1;
        return aplusb(xor_r, and_r);
    }
(递归-2)

int aplusb(int a, int b) { // recursive solution
        if (b == 0) return a;
        int xor_r = a ^ b;
        int carry_r = (a & b) << 1;
        return aplusb(xor_r, carry_r);
    }

(迭代)

int aplusb(int a, int b) { // iterative solution
        int xor_r = a ^ b;
        int carry_r = (a & b) << 1;
        while (carry_r){
            int pre_xor = xor_r;
            xor_r = xor_r ^ carry_r;
            carry_r = (pre_xor & carry_r) << 1;
        }
        return xor_r;
    }

思路:

同样是借助位运算,而且把两个加数转换成二进制数。

  1. 此处使用了异或运算 ('^')。由定义可知,‘^’运算结果为1的位加法结果也应为1,而‘^’运算结果为0的值有两种情况:两数同一位全0或者全1。两数同一位全0,结果自然是0 (和异或结果一致),全1时需要“特别处理”。
  2. 同上一解法,与运算的结果为1的位,两数在此位全1,需要进位(1 + 1 = 10)。 所以可以直接对‘&’运算的结果作左移运算(“<<”),使之进位。
  3. 所以若将左移的‘&’运算结果和‘^’运算结果相加,可得正确加法结果。
  4. 然而根据要求,我们不能直接求和,所以问题转换为 对“左移的‘&’运算结果和“‘^’运算结果”两个新的加数求和。
  5. 此时可以重复1-4步(实现可用递归或迭代),直到不需要“特别处理”为止,即不再有进位。可知此时‘&’运算结果为0,而‘^’运算结果即所求

附:

异或运算定义a⊕b = (¬a ∧ b) ∨ (a ∧¬b), 即a、b不相等时为1,相等时为0.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值