算法:位操作总结

来源:互联网 发布:starbound mac 下载 编辑:程序博客网 时间:2024/04/29 00:34

https://discuss.leetcode.com/topic/50315/a-summary-how-to-use-bit-manipulation-to-solve-problems-easily-and-efficiently

位操作包括 AND OR XOR(^) NOT(~) XNOR(异或取反) 移位(>>,<<)
通过位操作能够达到简化程序的作用
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

下面是一些典型的位操作算法
Ex1:计算二进制数的1的位数(递归,n&(n-1)后1的位数少1个)
Ex2:判断是否是2的幂,4的幂。。。(以4为例,1的个数只有1个,且在偶数为上)
Ex3:^和&做加法

int getSum(int a, int b) {    return b==0? a:getSum(a^b, (a&b)<<1); //be careful                          //about the terminating condition;                    }

Ex4:求丢失的数(异或)
Ex5:求不超过N的最大的2次幂(先把右边的位全部赋值为1,在加1后向左移1位)
Ex6:32位整型反转

    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;    }

Ex7:按位与求两数共有的1的位的号

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

Ex8:找重复dna序列:例Given s = “AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT”,Return: [“AAAAACCCCC”, “CCCCCAAAAA”].

class Solution {public:    vector<string> findRepeatedDnaSequences(string s) {        int sLen = s.length();        vector<string> 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;    }};

Ex9:出现n/2次及以上的数

int majorityElement(vector<int>& nums) {    int len = sizeof(int)*8, size = nums.size();    int count = 0, mask = 1, ret = 0;    for(int i = 0; i < len; ++i) {        count = 0;        for(int j = 0; j < size; ++j)            if(mask & nums[j]) count++;        if(count > size/2) ret |= mask;        mask <<= 1;    }    return ret;}

Ex10:元素出现三次除一个元素之外,找single number

//inspired by logical circuit design and boolean algebra;//counter - unit of 3;//current   incoming  next//a b            c    a b//0 0            0    0 0//0 1            0    0 1//1 0            0    1 0//0 0            1    0 1//0 1            1    1 0//1 0            1    0 0//a = a&~b&~c + ~a&b&c;//b = ~a&b&~c + ~a&~b&c;//return a|b since the single number can appear once or twice;int singleNumber(vector<int>& nums) {    int t = 0, a = 0, b = 0;    for(int i = 0; i < nums.size(); ++i) {        t = (a&~b&~nums[i]) | (~a&b&nums[i]);        b = (~a&b&~nums[i]) | (~a&~b&nums[i]);        a = t;    }    return a | b;};

这个其实没看懂,懂的大神求教,THX

Ex11:字符串长度乘积(用26位来存储信息)

int maxProduct(vector<string>& words) {    vector<int> mask(words.size());    vector<int> lens(words.size());    for(int i = 0; i < words.size(); ++i) lens[i] = words[i].length();    int result = 0;    for (int i=0; i<words.size(); ++i) {        for (char c : words[i])            mask[i] |= 1 << (c - 'a');        for (int j=0; j<i; ++j)            if (!(mask[i] & mask[j]))                result = max(result, lens[i]*lens[j]);    }    return result;}

Ex12:计算0的个数,1的个数

// bitset::count#include <iostream>       // std::cout#include <string>         // std::string#include <bitset>         // std::bitsetint 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;}
0 0
原创粉丝点击