Bit manipulation Technieques

XXX. Bit Manipulation Techniques

Bit Operations
Optimization

Basics

Core operations: & (and), | (or), ~ (not), ^ (exclusive-or, xor), and shift operators << and >>

  • Set union A | B
  • Set intersection A & B
  • Set subtraction A & ~B
  • Set negation ALL_BITS ^ A or ~A
  • Set bit A |= 1 << bit
  • Clear bit A &= ~(1 << bit)
  • Test bit (A & 1 << bit) != 0
  • Extract last bit A&-A or A&~(A-1) or x^(x&(x-1))
  • Remove last bit A&(A-1)
  • Get all 1-bits ~0

Examples


// Count ones in binary representation
int count_one(int n) {
    while(n) {
        n = n&(n-1);
        count++;
    }
    return count;
}

// Check if number is power of four
bool isPowerOfFour(int n) {
    return !(n&(n-1)) && (n&0x55555555);
}

^ tricks


// Add two integers using XOR
int getSum(int a, int b) {
    return b==0? a:getSum(a^b, (a&b)<<1);
}

// Find missing number
int missingNumber(vector& nums) {
    int ret = 0;
    for(int i = 0; i < nums.size(); ++i) {
        ret ^= i;
        ret ^= nums[i];
    }
    return ret^=nums.size();
}

| tricks


// Find largest power of 2
long largest_power(long 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;
}

// Reverse bits
uint32_t reverseBits(uint32_t n) {
    unsigned int mask = 1<<31, res = 0;
    for(int i = 0; i < 32; ++i) {
        if(n & 1) res |= mask;
        mask >>= 1;
        n >>= 1;
    }
    return res;
}

& tricks


// Reverse bits using masks
x = ((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1);
x = ((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2);
x = ((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4);
x = ((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8);
x = ((x & 0xffff0000) >> 16) | ((x & 0x0000ffff) << 16);

// Range Bitwise AND
int rangeBitwiseAnd(int m, int n) {
    int a = 0;
    while(m != n) {
        m >>= 1;
        n >>= 1;
        a++;
    }
    return m<

Applications


// DNA Sequences
class Solution {
public:
    vector findRepeatedDnaSequences(string s) {
        int sLen = s.length();
        vector v;
        if(sLen < 11) return v;
        char keyMap[1<<21]{0};
        int hashKey = 0;
        for(int i = 0; i < 9; ++i) 
            hashKey = (hashKey<<2) | (s[i]-'A'+1)%5;
        for(int i = 9; i < sLen; ++i) {
            if(keyMap[hashKey = ((hashKey<<2)|(s[i]-'A'+1)%5)&0xfffff]++ == 1)
                v.push_back(s.substr(i-9, 10));
        }
        return v;
    }
};

Sets


// Generate all subsets
vector> subsets(vector& nums) {
    vector> vv;
    int size = nums.size(); 
    if(size == 0) return vv;
    int num = 1 << size;
    vv.resize(num);
    for(int i = 0; i < num; ++i) {
        for(int j = 0; j < size; ++j)
            if((1<

Bitset


// Bitset example
int main () {
    std::bitset<8> foo (std::string("10110011"));
    std::cout << foo << " has ";
    std::cout << foo.count() << " ones and ";
    std::cout << (foo.size()-foo.count()) << " zeros.\n";
    return 0;
}
Previous
Previous

Sum of two integers

Next
Next

Increasing Triplet Subsequence