1. 程式人生 > >LeetCode編程訓練 - 位運算(bit manipulation)

LeetCode編程訓練 - 位運算(bit manipulation)

stack loop 題解 https mask ESS mingw numbers 去掉

位運算基礎

說到與(&)、或(|)、非(~)、異或(^)、位移等位運算,就得說到位運算的各種奇淫巧技,下面分運算符說明。

1. 與(&)

計算式 a&b,a、b各位中同為 1 才為 1,否則為0,a&1和a%2效果一樣;來看兩道典型的題目,第1道計算整數二進制中 1 的位數:

    //191. Number of 1 Bits
    int hammingWeight(uint32_t n) {
        int res=0;
        while(n!=0){
            n=n&(n-1);
            
++res; } return res; }

n=n&(n-1)代表去掉整數n二進制中最左側為 1 的位,例如n=12,則:

n    -> 1 1 0 0
            &
n-1  -> 1 0 1 1
------------------
        1 0 0 0

第2道判斷一個數是否為4的乘方數(不能用loop解):

    //342. Power of Four
    bool isPowerOfFour(int num) {
        if(num==INT_MIN) return
false; return !(num&(num-1)) && (num&0x55555555); }

以上0x55555555的二進制表示為……01010101 (偶數位為0、奇數位為1),像這樣tricky的數還有:

0xaaaaaaaa : 10101010101010101010101010101010 (偶數位為1,奇數位為0)
0x33333333 : 00110011001100110011001100110011 (1和0每隔兩位交替出現)
0xcccccccc : 11001100110011001100110011001100 (0和1每隔兩位交替出現)
0x0f0f0f0f : 00001111000011110000111100001111
(1和0每隔四位交替出現) 0xf0f0f0f0 : 11110000111100001111000011110000 (0和1每隔四位交替出現)

相關LeetCode題:

191. Number of 1 Bits 題解

342. Power of Four 題解

201. Bitwise AND of Numbers Range 題解

2. 或(|)

計算式a|b,a、b各位中有一個為1則結果為1;來看一道題:有正整數n,求小於或等於n的2的最大乘方數(不能用loop解):

int largest_power(ing N) {
    N = N | (N>>1);
    N = N | (N>>2);
    N = N | (N>>4);
    N = N | (N>>8);
    N = N | (N>>16);
    return (N+1)>>1;
}

看起來是不是相當tricky,其思路是用或運算將右邊位數置為1,例如n=01010,通過或操作n變為01111,則n+1為10000,所求為01000;更詳細解釋見 這裏

相關LeetCode題:

190. Reverse Bits 題解

898. Bitwise ORs of Subarrays 題解

3. 異或(^)

計算式a^b,a、b對應位相同為0,相異則為1;根據異或性質有a^a=0,a^0=a,利用該性質可解決136. Single Number:

    //136. Single Number
    int singleNumber(vector<int>& nums) {
        int res=0;
        for(auto x:nums) res^=x;
        return res;
    }

相關LeetCode題:

136. Single Number 題解

461. Hamming Distance 題解

371. Sum of Two Integers 題解

260. Single Number III 題解

4. 位移

a<<1效果相當於a*2(不超出數值類型範圍情況下),a>>1效果相當於a/2,位移常用於按位輪詢。

相關LeetCode題:

405. Convert a Number to Hexadecimal 題解

751. IP to CIDR 題解 逐位計算結果

有意思的時當我們的目光放到bit的維度,一些問題可以按位來求解,例如169. Majority Element求數組中出現次數大於一半的數:

    //169. Majority Element
    int majorityElement(vector<int>& nums) {
        int mask=1,size=nums.size(),ret=0;
        for(int i=0;i<32;i++){
            int count=0;
            for(int j=0;j<size;j++){
                if(nums[j]&mask) count++;
                if(count>size/2){
                    ret|=mask;    //逐位計算結果break;
                }
            }
            mask<<=1;
        }
        return ret;
    }

相關LeetCode題:

169. Majority Element 題解

477. Total Hamming Distance 題解

421. Maximum XOR of Two Numbers in an Array 題解

使用bit表示數據

在一些場景下我們希望用bit來表示數據,或節省空間或利用bit的運算特性來表示狀態轉換。

相關LeetCode題:

187. Repeated DNA Sequences 題解

289. Game of Life 題解

LeetCode編程訓練 - 位運算(bit manipulation)