常见的位运算有:
&(有0则为0):001 & 101 = 001
|(有1则为1): 001 | 101 = 101
^(异或,相异则为1):001 ^ 101 = 100
~(取反):~111 = 000
>>(右移):1101 >> 1 = 110
<<(左移) 1101 << 1 = 11010
题目1:判断一个数是否为2的幂次方
//解法一:
//1进行左移得到了int类型的最大值,再mod n如果得到0,则n仅有因子2
class Solution{
public:
bool isPowerOftwo(int n){
return n > 0 && (1<<30) % n == 0;
}
}
//解法二:
//n & -n表示的是从低位起到高位的第一个1;
//2的整次幂二进制表示中仅有一个1
class Solution{
public:
bool isPowerOftwo(int n){
return n > 0 && (n & -n) == n;
}
}
题目2:给定一个区间 [L,R] ,判断在这区间内的一个数,若二进制表示中1的个数为质数,输出共有几个这样的数。例:21->10101,1的个数为3,则21满足条件。
class Solution{
public:
int countPrimeSetBits(int L,int R){
unodered_set<int> primes({2,3,5,7,11,13,17,19});//先列出20以内的所有素数(例子)
int res = 0;
for(int i = 0;i <= R;i++){
int s = 0;
for(int k = i;k;k>>=1) s += k & 1;//得到该数二进制中总共几个1,每次&完对k进行加1
if(primes.count(s))
res++;
}
return res;
}
}
题目3:给定一个数组,仅有一个数出现次数是奇数,其余均为偶数次,将奇数次的数找出来。(不能使用额外的空间--->可以使用O(1)的空间)
/*
a ^ a = 0
0 ^ a = a
任何数异或自身都为0,而0异或任何数结果为任何数本身。
*/
class Solution{
public:
int singleNumber(vector<int> &nums){
int res = 0;
for(auto x : nums) res ^= x;//异或具备交换律,间隔碰到相同的变为0
return res;
}
}
题目4:给定一定整数,求出该整数的反码。
class Solution{
public:
int findComplement(int num){
int res = 0,t = 0;
while(num){
res += !(num & 1) << t;
num >> =1,t++;
}
return res;
}
}
题目5:给定一个数组,仅有两个数出现了1次,其他数出现了2次,找出出现1次的数。(仅使用O(1)的空间)
class Solution{
public:
vector<int> singleNumber(vector<int> &nums){
int s = 0;
for(auto x : nums) s ^= x;
int k = 0;
while(!(s >> k & 1)) k++;
int s2 = 0;
for(auto x : nums){
if(x >> k & 1)
s2 ^= x;
return vector<int>({s2,s ^ s2});
}
}
}