1. 程式人生 > >位運算面試題常用技巧

位運算面試題常用技巧

位運算是面試中的常見考題一種,位操作有~, <<, >>, &, |, ^六種。

左移和右移規則

對左移而言,移動正數和負數規則是相同的;對於右移而言,則有些差別,正數補0,負數補1。
舉例說明:
對於一個16位的整數:0000 0000 0000 0101,左移一位是0000 0000 0000 1010,右移一位是0000 0000 0000 0010
對於一個16位的負數:1000 0000 0000 0101,左移一位是0000 0000 0000 1010,右移一位是1100 0000 0000 0010

下面通過幾個典型的題目來透徹分析位運算的一些常用技巧。

技巧一:

對於正整數,左移一位,就是將數值乘2;右移一位就運算數值除2;但是位操作的效率要比運算子高。

技巧二:

一個數和另一個數異或兩次得到的還是原來的數

題:不用臨時變數交換兩個整數。

a = a ^ b;
b = a ^ b;
a = a ^ b;

技巧三:

n & (n - 1)將整數n的最後一位為1的位變成0

  • 題:統計一個整數中二進位制位上1的個數。
int fun(int num)
{
    int count = 0;
    while(num)
    {
        num = num & (num - 1);
        ++count;
    }
    return count;
}
  • 題:判斷一個數是不是2的冪。
//返回0表示是2的冪,返回非0值表示不是2的冪
int
fun(int num) { return n & (n - 1); }

解析:如果一個數是2的冪,則其有且只有一位為1。因此,消除這一位後就會變成0

  • 題:判斷一個32位整數是不是4的冪
//返回0表示不是4的冪,返回非0表示是4的冪
int fun(int num)
{
    if(!(n & (n - 1)))
    {
        return (n & 0x55555555);
    }
    return 0;
}

解析:是4的冪的數一定是2的冪,因此先判斷是不是2的冪,2的冪中1在基數位上的是4的冪,與0x55555555按位與,如果在基數位上有數則不為0

  • 題:輸入兩個整數m和n,計算需要改變多少位能使m變成n
int fun(int m, int n)
{
    //將m和n按位異或,相同的位為0,不同的位為1
    m = m ^ n;
    int count = 0;
    //統計不同的位有多少個就ok
    while(m)
    {
        m = m & (m - 1);
        ++count;
    }
    return count;
}

技巧四:

n & (~n + 1)提取出整數n最後一位為1的數
舉例:n = 01101,~n是將n按位取反就是10010,~n + 1 = 10011,最後,n & (~n + 1) = 00001

  • 題:統計一個整數中二進位制位上1的個數。
int fun(int num)
{
    int count = 0;
    while(num)
    {
        n -= n & (~n + 1);
        ++count;
    }
    return count;
}

技巧五:

不使用+,-,*,/完成整數相加

 int Add(int num1, int num2)
 {
     int sum, carry;
     do{
         //將兩個數異或,模擬加法中相加不進位的結果
         sum = num1 ^ num2;
         //只考慮進位的情況
         carry = (num1 & num2) << 1;
         num1 = sum;
         num2 = carry;
     }
     while(num2 != 0); //將結果相加的過程就重複上述過程,直到進位為0

     return sum;
 }

舉例分析程式碼過程:
將12(二進位制表示為0000 1100)與5(二進位制表示為0000 0101)相加

第一次迴圈:
0000 1100 ^ 0000 0101 = 0000 1001
(0000 1100 & 0000 0101) << 1 = 0000 1000

第二次迴圈:
(0000 1001 ^ 0000 1000) = 0000 0001
(0000 1001 & 0000 1000) << 1 = 0001 0000

第三次迴圈:
(0000 0001 ^ 0001 0000) = 0001 0001
(0000 0001 & 0001 0000) << 1 = 0000 0000

迴圈結束
結果為0001 0001 = 17

僅以此文紀念2017年阿里內推失敗,校招繼續加油。