位运算
一、含义
1、常用位操作
1)判断奇偶性:
(x & 1)== 1 等价于(x % 2 == 1)奇数
(x & 1)== 0 等价于(x % 2 == 0)偶数
2)x / 2 等价于 x>>1
3)x &=(x - 1)等价于 把x最低位的二进制1给去掉
4)x & -x 等价于 x & (~x+1) 即得到最低位1
5)x & ~x 等于 0
6)~0:表示全为1的数
7)0与任何数异或 = 原数;相同的两个数异或 = 0
2、指定位置的位运算
1)将 x 最右边的 n 位清零:x & (~0 << n)
2)获取 x 的第 n 位值:(x >> n)& 1
3)获取 x 的第 n 位的幂值:x & (1 << n)
4)仅将第 n 位置为 1:x |=(1<<n)
5)仅将第 n 位置为 0:x |=(~(1<<n))
6)将 x 最高位至第 n 位(含)清零:x & ((1 << n) - 1)
7)将第 n 位至第 0 位(含)清零:x &(~((1 << (n + 1)) - 1))
二、题解
1、191. 位1的个数
方法一:
1)当一个数被减1时,它最右边的那个值为1的bit将变为0,同时其右边的所有的bit都会变成1
2)每次执行n&(n-1)的作用就是把x对应的二进制数中的最后一位1去掉。因此,循环执行这个操作直到x等于0的时候,循环的次数就是x对应的二进制数中1的个数。
方法二:
通过 n & 1 ( n % 2)来统计当前 n 的最低位是否为1,同时每次直接对n进行右移并高位补0
#include<stdio.h>
int func(int x)
{
int countx = 0;
while(x)
{
countx++;
x &= x-1;
//count += (n & 1); // n % 2
//n >>= 1;
}
return countx;
}
int main(void)
{
int n = 9;
printf("%d里有%d个1\n",n ,func(n));
return 0;
}
2、求解二进制中0的个数
#include<stdio.h>
int ZeroNum(int n)
{
int count = 0;
while(n+1)
{
count++;
n |= (n+1);
}
return count;
}
int main(void)
{
int value = 25;
int ret = ZeroNum(value);
printf("%d中有%d个0\n",value, ret);
return 0;
}
3、设置或清除某一位的值
给定一个变量a,写两段代码,第一个设置a的bit3,第二个清除a的bit3.在以上两个操作中,要保持其他位不变。
#include<stdio.h>
#define BIT3 (0x1<<3)
static int a;
/*设置bit3*/
void set_bit3(void)
{
a |= BIT3;
}
/*清除bit3*/
void clear_bit3(void)
{
a &= ~BIT3;
}
4、136. 只出现一次的数字
方法一:异或法
0与任何数异或 = 原数
相同的两个数异或 = 0
方法二:哈希表map< key, value >
1、遍历一遍数组,将所有元素插入到哈希表中;
2、遍历数组,如果该元素对应的键值 == 1,则返回该元素。
方法三:集合set< int >
1、遍历整个数组,如果集合中存在该元素,就将其删除,否则将其插入到该集合中;
2、最终该集合中只有一个元素,返回集合首元素。
class Solution {
public:
int singleNumber(vector<int>& nums) {
//异或法
int ret = 0;
for(auto x : nums){
ret ^= x;
}
return ret;
}
};
class Solution {
public:
int singleNumber(vector<int>& nums) {
//哈希表map
unordered_map<int , int>map;
for(auto i : nums) map[i]++;
for(auto i : nums) {
if(map[i] == 1) return i;
}
return 0;
}
};
class Solution {
public:
int singleNumber(vector<int>& nums) {
//集合set
unordered_set<int>set;
for(auto i : nums){
if(set.count(i) == 1) {
set.erase(i);
}else{
set.insert(i);
}
}
return *set.begin();
}
};
5、231. 2 的幂
恒有 n & (n - 1) == 0
恒有 n & (-n) == n
class Solution {
public:
bool isPowerOfTwo(int n) {
// return (n > 0 && (n&(n-1)) == 0);
return (n > 0 && (n&(-n)) == n);
}
};