lintcode 中等題:A + B Problem A + B 問題


題目:

給出兩個整數a和b, 求他們的和, 但不能使用 + 等數學運算符。

如果 a=1 並且 b=2,返回3

注意

你不需要從輸入流讀入數據,只需要根據aplusb的兩個參數a和b,計算他們的和並返回就行。

挑戰

顯然你可以直接 return a + b,但是你是否可以挑戰一下不這樣做?

說明

a和b都是 32位 整數么?

  • 是的

我可以使用位運算符么?

  • 當然可以 

解題

上面提示了用位運算,通過不能夠用加法,應該也會用到邏輯運算,感覺應該提取a、b的每位數據進行計算,也就是:a1 = a & 1 ,b1 = b & 1 這個就把a、b的最低位提取出來了,同時在進行下一位計算的時候a、b要右移一位,也就是 a = a>> 1 、b = b>> 1,下面問題是中間該怎么搞?參考博客

a1、b1是a、b的對應位,carry1上一位的進位數,carry2是這一位的進位數,val是a1、b1、carry的和,計算結果有下表:

a1 b1 carry1 carry1 val
0 0 0 0 0
0 0 1 0 1
0 1 0 0 1
1 0 0 0 1
1 1 1 1 1
1 1 0 1 0
1 0 1 1 0
0 1 1 1 0

下面即簡單又不簡單

val是第i位的數,carry2是要進位的數,下一輪循環將會代替carry1

val應該在第i位,左移i位可以解決問題,val = val << i

sum 用來保存結果,初始值是 0 ,sum和val進行或運算,<只要有一個1 就是1>,在進行地位運算的時候,高位都是0,也就是主要判斷val的值是不是1的問題,sum = sum | val  

這里的過程還真的不好想的

下一輪循環就是 a = a >> 1 b = b >> 1

Java程序:

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.
        int sum = 0 ;
        int carry = 0;
        for(int i = 0;i< 32 ;i++){
            int a1 = a & 1;
            int b1 = b & 1;
            int val = 0 ;
            if(a1 == 0 && b1 == 0 && carry == 0){
                val = 0;
                carry = 0;
            }else if(a1 == 1 && b1 == 1 && carry == 1){
                val = 1;
                carry = 1;
            }else if(a1==0 && b1 ==0 || a1 ==0 && carry ==0 || b1 ==0 && carry ==0){
                val = 1;
                carry = 0;
            }else{
                val = 0;
                carry = 1;
            }
            val = val << i;
            sum = sum | val;
            a = a >> 1;
            b = b >> 1;
        }
        return sum;
    }
};
View Code

總耗時: 660 ms

Python程序:

class Solution:
    """
    @param a: The first integer
    @param b: The second integer
    @return:  The sum of a and b
    """
    def aplusb(self, a, b):
        # write your code here, try to do it without arithmetic operators.
        sum = 0 
        carry = 0
        for i in range(32):
            a1 = a & 1
            b1 = b & 1
            val = 0
            if a1== 0 and b1 ==0 and carry ==0:
                val =0
                carry = 0
            elif a1 == 1 and b1 == 1 and carry ==1:
                val =1 
                carry =1
            elif a1 == 0 and b1 ==0 or a1==0 and carry ==0 or b1 ==0 and carry ==0:
                val = 1
                carry = 0
            else:
                val = 0
                carry = 1
            val = val << i
            sum = sum|val
            a = a>>1
            b = b>>1
        return sum
View Code

總耗時: 203 ms

這樣寫還是很好理解的,在上面的博客鏈接中,還有另外一種方法,比較不好理解。

異或運算^  與運算 &   加法運算<考慮進位>  加法運算<不考慮進位>

0 ^ 0 = 0  0 & 0 = 0  0 + 0 = 0        0 + 0 = 0

1 ^ 0 = 1  1 & 0 =  0   1 + 0 =  1        1 + 0 = 1

1 ^ 1 = 0  1 & 1 = 1  1 + 1 = 10       1 + 1 = 0

0 ^ 1 = 1  0 & 1 = 0  0 + 1 = 1         0 + 1 = 1

可以看出加法不考慮進位的情況下和異或運算結果是一樣的。

與運算結果是1時候,表示要進位 1.為了更好的計算,左移一位,這個就是要進位的,進位的在和上面的結果相加,出現了遞歸的現象了。

 sum = a ^ b

 carry= a&b

a = sum

b = carry

遞歸下去。。。 a b中有0的時候結束

OK

Java程序:

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(b==0)
            return a;
        return aplusb( a ^ b,(a&b)<<1);    
    
        
    }
};
View Code

總耗時: 586 ms

非遞歸程序:

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(b==0)
            return a;
        while(b!=0){
            int sum = a ^ b;
            int carry = (a&b)<<1 ;
            a = sum;
            b = carry;
            
        }
        return a;
    }
};
View Code

總耗時: 592 ms

上面中b后來被考慮成進位項,當所有位都沒有進位時候也就是b ==0 的時候結束程序。

注意在遞歸程序中:不應該增加a==0的時候結束程序,可能出現a =0但是會進位的情況。

上面程序無論是遞歸還是非遞歸都是出現時間超時的問題。

 

class Solution:
    """
    @param a: The first integer
    @param b: The second integer
    @return:  The sum of a and b
    """
    def aplusb(self, a, b):
        # write your code here, try to do it without arithmetic operators.
        if b == 0:
            return a
        if a == 0:
            return b
        while b!=0:
            carry = (a&b)<<1 
            a = a ^ b
            b = carry
        return a 
View Code

 

 

 

 都是這個數據的問題

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM