前言
这一节主要讲位运算的位与。
如果对位运算一点也不熟悉的朋友,可以看这篇文章,看完可了解基本概念,非常好用:
原文链接:《位操作》
目录
位与的应用
1.判断奇偶性
正常的判断奇偶性代码是这样的:
比如要判断奇数
bool is_odd(int num)
{
if (num % 2 == 1)
{
//奇数
return true;
}
else
{
//偶数
return false;
}
}
而利用位操作也可以
代码:
bool is_odd(int num)
{
if (num & 1 == 1)
{
//奇数
return true;
}
else if (num & 1 == 0)
{
//偶数
return false;
}
}
原因:一个数字的二进制表示,末尾不是1就是0,所以与 1 进行与运算,即可判断奇偶性。
2. 2的幂判定
给定一个数字,那么可以利用下面的代码来判断此数字是否为偶数。
(x & (x - 1)) == 0
直接看图:
3. 计算二进制数中“1”的个数
代码:
int hammingWeight(uint32_t n)
{
int count = 0;
while (n)
{
n &= (n - 1);
++count;
}
return count;
}
图示:
对当前数字一直减一再位与,到最后为零
__builtin_popcount()
这个函数可以直接计算二进制数中“1”的个数。。。
习题
序号 | 题目 |
---|---|
1 | 191. 位1的个数 |
2 | 剑指 Offer 15. 二进制中1的个数 |
3 | 231. 2 的幂 |
4 | 1356. 根据数字二进制下 1 的数目排序 |
5 | 762. 二进制表示中质数个计算置位 |
题解
191. 位1的个数
原题链接:191. 位1的个数
代码
class Solution {
public:
int hammingWeight(uint32_t n)
{
int count = 0;
while (n)
{
n &= (n - 1);
++count;
}
return count;
}
};
剑指 Offer 15. 二进制中1的个数
代码
class Solution {
public:
int hammingWeight(uint32_t n)
{
int count = 0;
while (n)
{
n &= (n - 1);
++count;
}
return count;
}
};
231. 2 的幂
原题链接:231. 2 的幂
法一:换底公式(log)
class Solution {
public:
bool isPowerOfTwo(int n)
{
if (n <= 0) return false;
int x = (int)(log2(n) / log2(2) + 1e-8);
return fabs(n - pow(2, x)) < 1e-8;
}
};
法二:位运算
bool isPowerOfTwo(int n)
{
return n > 0 && (n & (-n)) == n;
}
bool isPowerOfTwo(int n)
{
return (n > 0 && (n & (n - 1)) == 0);
}
1356. 根据数字二进制下 1 的数目排序
代码
修改 sort()
int num_of_one(int n)
{
int count = 0;
while (n)
{
n &= (n - 1);
++count;
}
return count;
}
bool compare(int a, int b)
{
return (num_of_one(a) < num_of_one(b) || num_of_one(a) == num_of_one(b) && a < b);
}
class Solution {
public:
vector<int> sortByBits(vector<int>& arr)
{
sort(arr.begin(), arr.end(), compare);
return arr;
}
};
762. 二进制表示中质数个计算置位
原题链接:762. 二进制表示中质数个计算置位
分析
题目是要求:
给定范围内,每个数的二进制的1的个数是否为质数,计算它们的数目。
做法:根据题目范围,申请一个数组用来表示是否为质数。
int isprimer[20] = {0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1};
遍历一遍,对每个数字求二进制1的个数,再去数组中查看是否为质数。
代码
class Solution {
public:
int countPrimeSetBits(int left, int right)
{
int isprimer[20] = {0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1};
int ans = 0;
for ( ; left <= right; ++left)
{
ans += isprimer[__builtin_popcount(left)];
}
return ans;
}
};
end
原文链接: 《算法零基础100讲》(第42讲) 位运算 (位与) 入门
作者:英雄哪里出来