位運算

基礎知識

位運算是把數字用二進制表示之後,對每一位上0或1的運算。位運算總共只有5種運算:與、或、異或、左移和右移。對於異或操作,需要注意一下0^0=0; 1^1=0; 1^0=1

應用:二進制中1的個數

題目:請實現一個函數,輸入一個整數,輸出該數二進制表示中1的個數。例如把9表示成二進制是1001,有2位是1.因此如果輸入9,該函數輸出2。
分析對於負數1000 0000右移一位的時候,得到1100 0000而非0100 0000。因此如下方法對於負數會進入死循環:

int NumberOf1(int n) {
    int count=0;
    while(n){
        if(n&1) count++;
        n=n>>1;
    }
    return count;
}

代碼實現
//解法一,不右移n,左移1

int NumberOf1(int n) {
    int count=0;
    unsigned int flag=1;
    while(n){
        if(n&flag) count++;
        flag=flag<<1;
    }
    return count;
}

//解法二,基於這樣一個規律:我們把一個整數減去1,都是把最右邊的1變成0;並且如果它右邊還有0的話,所有的0都變成1,而它左邊所有位都保持不變。

int NumberOf1(int n) {
    int count=0;
    while(n){
        ++count;
        n=(n-1)&n;
    }
    return count;
}

應用:不用加減乘除做加法

題目:寫一個函數,求兩個整數之和,要求在函數體內不得使用+、-、*、÷四則運算符號。
分析:分三步:第一步只做各位相加不進位,第二步做進位,第三步將前面兩個結果加起來,即重複前兩位,直到不產生進位爲止。
代碼實現

int Add(int num1, int num2) {
    int sum, carry;
    while (1) {
        sum = num1^num2;
        carry = (num1&num2) << 1;
        num1 = sum;
        num2 = carry;
        if (num2 == 0) return num1;
    }
}

測試用例

Add(5, 17);
Add(0, 17);
Add(5, 0);

應用:數組中只出現一次的數字

題目:一個整型數組裏除了兩個數字之外,其他的數字都出現了兩次。請寫程序找出這兩個只出現一次的數字。要求時間複雜度是O(n),空間複雜度是O(1)。
分析:首先,大家都對“數組中只有一個只出現一次的數字”這個題目比較熟悉,直接遍歷一遍異或即可得解。出現兩個數字怎麼辦呢?至少有一種思路是將這個數組分爲兩個數組,每個數組只有一個只出現一次的數字。問題又來了,怎麼得到這兩個數組呢?答:異或遍歷一遍,得到的即爲兩個只出現一次數字的異或值;這個異或值若某一位上爲1,那需要找的兩個數在這一位上必定不相同;因此可以根據這一位是否爲1將原數組分爲兩個數組。
代碼實現

int findFirstBitOfOne(int num){
    int count=0;
    int flag=1;
    while(num & flag==0){
        count++:
        flag =flag<< 1;
    }
    return count;
}

void findNumsOnlyOnce(vector<int> array, int& num1, int& num2){
    int len=array.size();  //假設輸入數據符合規則
    if(len<2){
        num1=array.at(0);
        num2=array.at(1);
        return;
    }
    int nor=0;
    for(int i=0; i<len; i++){
        nor ^= array.at(i);
    }
    int flag= 1 << findFirstBitOfOne(nor);
    num1=0;num2=0;
    for(int i=0; i<len; i++){
        if(array.at(i)&flag == 0){
            num1 ^= array.at(i);
        }
        else{
            num2 ^= array.at(i);
        }
    }
    return;
}
發佈了419 篇原創文章 · 獲贊 248 · 訪問量 125萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章