算法-不使用加減法符號實現兩數相加減,兩種實現方式

Leetcode-371

不使用運算符 + 和 - ​​​​​​​,計算兩整數 ​​​​​​​a 、b ​​​​​​​之和。

示例 1:

輸入: a = 1, b = 2
輸出: 3
示例 2:

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

1、不使用加減法符號實現加法(I)

看到大佬們給出的代碼的確很簡潔,但是同樣的,也很難懂,這裏給出一種非常直觀的解法
主要思路:
1、從1<<0到1<<31做掩碼,遍歷一下,分別與a和b按位與,檢測對應位
2、如果對應位都爲1,那麼進一位:result|=mask<<1;
3、如果對應位只有一個爲1,且result在當前位爲0,那麼將當前位置1
4、如果對應位只有一個爲1,且result在當前位爲1,那麼將當前位置0,再進1位
5、返回result

    public int getSum1(int a, int b) {
        int result=0;
        for(int i=0;i<32;i++){
            int mask=1<<i;
            if((a&mask)!=0&&(b&mask)!=0){//兩個都是1,必然進位
                result|=mask<<1;
            }else if(!(((a&mask)==0)&&((b&mask)==0))){
                if((result&mask)==0){
                    result|=mask;
                }else{
                    result&=~mask;//清除原來位
                    result|=mask<<1;//進一位
                }
            }
        }
        return result;
    }

上面的寫法其實是沒有問題的,雖然得到mask的時候使用到了++運算符。
++運算符對應的彙編指令映射到X86後其實是INC,而+映射的是ADD。但++看起來還是有點不順眼。

爲了避免這種比較尷尬情況,我們其實可以換個思路,mask其實是可以由自身得到的,即每輪循環過後,mask=mask<<1;直到mask==1<<31的時候終止循環。這樣我們就得到一個純位運算得到的加法。


    public int getSum(int a, int b) {
        int result=0;
        int mask=0;
        while(true){
            mask=mask==0?1:mask<<1;
            if((a&mask)!=0&&(b&mask)!=0){//兩個都是1,必然進位
                result|=mask<<1;
            }else if(!(((a&mask)==0)&&((b&mask)==0))){//其中某一個爲1
                if((result&mask)==0){//如果現在位是0,那麼將現在位變成1
                    result|=mask;
                }else{//如果現在位是1,那麼要將當前位置0,高位放置1
                    result&=~mask;//清除原來位
                    result|=mask<<1;//進一位
                }
            }
            if(mask==1<<31){
                break;
            }
        }
        return result;
    }

2、不使用加減法符號實現加法(II)

大佬們給出的簡潔代碼如下所示:

    public int getSum(int a, int b) {
    	while (b != 0) {
            int temp=a^b;//無進位累加值
            int carry=(a&b)<<1;//進位值
            //a=無進位累加值 b=進位值
            a=temp;
            b=carry;
        }
        return a;
    }

簡單解釋一下:
1、無進位的加法使用異或實現
2、進位值爲a和b的最高位決定,兩個最高位均爲1,則進1位,而a和b的最高位可以由a&b獲得,這比較好理解,然後如果他們的最高位按位與的結果爲最高位1,那麼向左再移動一位,即爲進位。直到進位爲0,說明運算結束。

3、不使用加減法符號實現減法

如何實現減法呢?這就要考慮到正負數的轉換問題了,負數=正數按位取反+1

    public int getSub(int a, int b) {
    	b=~b;//獲得-b
    	b++;
    	while (b != 0) {
            int temp=a^b;//無進位累加值
            int carry=(a&b)<<1;//進位值
            //a=無進位累加值 b=進位值
            a=temp;
            b=carry;
        }
        return a;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章