LintCode - A + B 問題(普通)

weixin_33782386發表於2016-11-20

版權宣告:本文參考網路文章。

難度:普通
要求:

給出兩個整數a和b, 求他們的和, 但不能使用 +等數學運算子。
** 注意事項
你不需要從輸入流讀入資料,只需要根據aplusb的兩個引數a和b,計算他們的和並返回就行。
說明
a和b都是 32位
整數麼?
是的
我可以使用位運算子麼?
當然可以
樣例如果 a=1並且 b=2,返回3

思路:

用位運算實現加法也就是計算機用二進位制進行運算,32位的CPU只能表示32位內的數,這裡先用1位數的加法來進行,在不考慮進位的基礎上,如下
1 + 1 = 0
1 + 0 = 1
0 + 1 = 1
0 + 0 = 0

很明顯這幾個表示式可以用位運算的“^”來代替,如下
1 ^ 1 = 0
1 ^ 0 = 1
0 ^ 1 = 1
0 ^ 0 = 0

這樣我們就完成了簡單的一位數加法,那麼要進行二位的加法,這個方法可行不可行呢?肯定是不行的,矛盾就在於,如何去獲取進位?要獲取進位我們可以如下思考:
0 + 0 = 0
1 + 0 = 0
0 + 1 = 0
1 + 1 = 1
//換個角度看就是這樣
0 & 0 = 不進位
1 & 0 = 不進位
0 & 1 = 不進位
1 & 1 = 進位

正好,在位運算中,我們用“<<”表示向左移動一位,也就是“進位”。那麼我們就可以得到如下的表示式
//進位可以用如下表示:
(x&y)<<1

到這裡,我們基本上擁有了這樣兩個表示式
x^y //執行加法
(x&y)<<1 //進位操作

現總結如下:

定理1:
設a,b為兩個二進位制數,則a+b = a^b + (a&b)<<1。證明:a^b是不考慮進位時加法結果。當二進位制位同時為1時,才有進位,因此 (a&b)<<1是進位產生的值,稱為進位補償。將兩者相加便是完整加法結果。
定理2:
使用定理1可以實現只用位運算進行加法運算。證明:利用定理1中的等式不停對自身進行迭代。每迭代一次,進位補償右邊就多一位0,因此最多需要加數二進位制位長度次迭代,進位補償就變為0,這時運算結束。

class Solution {
    /*
     * param a: The first integer
     * param b: The second integer
     * return: The sum of a and b
     */
    public int aplusb(int a, int b) {
        // write your code here, try to do it without arithmetic operators.
        if(a==0)return b;  
        if(b==0)return a;  
        int x = a^b;  //記錄不進位數
        int y = (a&b)<<1;  //記錄進位數
        return aplusb(x,y); //然後遞迴 上述不進位結果 + 進位結果,最終進位為0,則返回最終結果
    }
};

相關文章