位元位操作演算法題匯總

來源:互聯網
上載者:User

涉及位元位操作的演算法題有很多,本文對其中常見的一些進行匯總,所有資源來自網路。

一、判斷一個正整數是否是2的整數次冪

判斷一個整數N是否是2的整數次冪,這是個很常見的問題。比如4、8等都是2的整數次冪,而6不是。

解法1)一個基本的解法是設定i=1開始,迴圈乘以2直到i>=n,然後判斷i是否等於n即可。

解法2)當然還有一個更好的方法,那就是觀察一個數位二進位表示,如n=101000,則我們可以發現n-1=100111。也就是說n=>n-1是將n最右邊的1變成了0,同時將n最右邊的1右邊的所有位元位由0變成了1。因此如果n & (n-1) == 0就可以判定數字n為2的整數次冪。(注意一個地方,n=0為特殊情況,需要額外考慮,因此最終的判定運算式為n && !(n & (n-1)) ).

bool powOf2(int n){    return n && !(n & (n-1));}

二、求一個整數二進位表示中1的個數

如給定N=6,則它的二進位表示為0110,所以二進位表示中1的個數為2。

解法1)一個自然的方法是將N和1按位與,然後將N除以2,直到N為0為止。該演算法代碼如下

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

上面的代碼存在一個問題,那就是如果輸入為負數的話,會導致死迴圈,為瞭解決負數的問題,如果使用的是JAVA,可以直接使用無符號右移操作符>>>來解決,如果是在C/C++裡面,為了避免死迴圈,我們可以不右移輸入的數字i。首先i和1做與運算,判斷i的最低位是不是為1。接著把1左移一位得到2,再和i做與運算,就能判斷i的次高位是不是1……這樣反覆左移,每次都能判斷i的其中一位是不是1。基於此,我們得到如下代碼:

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

解法2)一個更好的解法是採用第一個題中類似的思路,每次n&(n-1)就能把n中最右邊的1變為0,所以很容易求的1的總數目。

int numOf1_2(int x){       int cnt = 0;    while (x != 0) {        x = x & (x-1);        cnt++;    }    return cnt;} 

 三、反轉一個不帶正負號的整數的所有位元位

給定一個不帶正負號的整數N,反轉該整數的所有位元位。例如有一個8位的數字01101001,則反轉後變成10010110,32位的不帶正負號的整數的反轉與之類似

解法1)自然的解法就是參照字串反轉的演算法,假設不帶正負號的整數有n位,先將第0位和第n位交換,然後是第1位和第n-1位交換...注意一點就是交換兩個位是可以通過異或操作XOR來實現的。因為0 XOR 0 = 0, 1 XOR 1 = 0, 0 XOR 1 = 1, 1 XOR 0 = 1,使用1異或0/1會讓其值反轉。

typedef unsigned int uint;uint swapBits(uint x, uint i, uint j){    uint lo = ((x >> i) & 1);  //取x的第i位的值    uint hi = ((x >> j) & 1);  //取x的第j位的值    if (lo ^ hi) {                     x ^= ((1U << i) | (1U << j)); //如果第i位和第j位值不同,則交換i和j這兩個位的值,使用異或操作實現    }    return x;}uint reverseXor(uint x){    uint n = sizeof(x) * 8;    for (uint i = 0; i < n/2; i++) {        x = swapBits(x, i, n-i-1);    }    return x;}

解法2)採用分治策略,首先交換數字x的相鄰位,然後再是2個位交換,然後是4個位交換...比如給定一個8位元01101010, 則首先交換相鄰位,變成10 01 01 01,然後交換相鄰的2個位,得到01 10 01 01,然後再是4個位交換,得到0101 0110。總的時間複雜度為O(lgN),其中N為整數的位元。下面給出一個反轉32位整數的代碼,如果整數是64位的可以以此類推。

uint reverseMask(uint x) {       assert(sizeof(x) == 4); // special case: only works for 4 bytes (32 bits).    x = ((x & 0x55555555) << 1) | ((x & 0xAAAAAAAA) >> 1);          x = ((x & 0x33333333) << 2) | ((x & 0xCCCCCCCC) >> 2);           x = ((x & 0x0F0F0F0F) << 4) | ((x & 0xF0F0F0F0) >> 4);          x = ((x & 0x00FF00FF) << 8) | ((x & 0xFF00FF00) >> 8);       x = ((x & 0x0000FFFF) << 16) | ((x & 0xFFFF0000) >> 16);       return x; }


 

 

 

,

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.