哈喽大家好,今天博主给大家带来算法基础常见位运算的模板,可以说大家遇到的百分之九十与位运算有关的题都可以用得上。话不多上我们上干货:
<<? ?左移运算符
>>? ?右移运算符
~? ? ? 取反
&? ? ?与运算
|? ? ? ?或运算
^? ? ? ?或非
?对于前三个,我们都很熟悉,我们重点说一下后三位,既然我们标题说有模板,那么大家只要记住博主给大家总结口诀就可以了:
非常通俗易懂吧
&? :? ? 0&0=1? ? ?1&0=0;????????有0就是0
|? ? ? ? ? ?1 | 1=1? ? ?1 | 0=1;? ? ? ? 有1就是1
^? ? ? ? ? 1^1=0? ? ?1^0=1? ? ? ? ? ? 相同为0,相异为1
n=0 1 1 0 1 0 1 0 0 1
首先第一个知识点是二进制最低位是右边,所以我们在计算的时候是从右边从零计数
比如我们选择第六位,想判断它是不是1,只要&1不就行了,如果结果是1,说明第六位是1,反之则0,怎么找到第六位,只要向右移动6位不就就行了么
????????
(n>>x)&1
x是我们要查找的位数
如果大家没搞懂原理,直接用模板就可以,固定用法
n=0 1 1 0 1 0 1 0 1
仅将第x位修改成1,首先我们得用<<操作符把第x位移动到最低位,一直或运算是有1就为1,那么我们直接或等1不就行了
n|=(1<<x)
n=0 1 1 0 1 0 1 1 0 0
只要与上一条反着思考就行了
n&=(~(1<<x))
n = 0 1 1 1 0 1 0 1 0 0 0
根据n的二进制,最右侧的1在第四位,我们最后就是要把这个数变成这样:
n & -n
n = 0 1 1 0 1 0 0 1?0
提取后,n就会变成这样:
?
n&(n-1)
由于五,六模板有一些抽象,下边博主给大家带来三道题,都是用这两个模板解决的题目,让大家更深刻的理解模板的用法以及应用场景:
观察这个运算:n?&?(n?1)? ?其运算结果恰为把 n?的二进制位中的最低位的 1?变为 0?之后的结果。
?题解:
class Solution {
public:
int hammingWeight(uint32_t n) {
int ret = 0;
while (n) {
n &= n - 1;
ret++;
}
return ret;
}
};
题解:
class Solution {
public int[] countBits(int n) {
int[] bits = new int[n + 1];
int highBit = 0;
for (int i = 1; i <= n; i++) {
if ((i & (i - 1)) == 0) {
highBit = i;
}
bits[i] = bits[i - highBit] + 1;
}
return bits;
}
}
class Solution {
public:
int countOnes(int x) {
int ones = 0;
while (x > 0) {
x &= (x - 1);
ones++;
}
return ones;
}
vector<int> countBits(int n) {
vector<int> bits(n + 1);
for (int i = 0; i <= n; i++) {
bits[i] = countOnes(i);
}
return bits;
}
};
给大家带来两道例题:
题解:
class Solution {
public:
int singleNumber(vector<int>& nums) {
int ret=0;
for(auto i :nums) ret^=i;
return ret;
}
};
260. 只出现一次的数字 III - 力扣(LeetCode)
题解:
class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
long long xs = 0;
for (int& x : nums) {
xs ^= x;
}
int lb = xs & -xs;
int a = 0;
for (int& x : nums) {
if (x & lb) {
a ^= x;
}
}
int b = xs ^ a;
return {a, b};
}
};
?
好的,常见的所有位运算的模板都给大家列在这篇博客了,希望有帮助大家不要吝啬自己手里的关注呀。