位操作包括 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::bitset
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;
}