
上篇谈到了位运算的相关语法及原理和部分基础题目配合讲解,本篇将结合进阶题目,深化对于位运算的掌握运用。
给定一个数组,该数组内除目标值外,其他值均出现了3次,要求找到该只出现一次的目标值。 时间复杂度为O(n),空间复杂度为O(1).
比特位计数:
设要找的数位 ret 。 由于整个数组中,需要找的元素只出现了「⼀次」,其余的数都出现的「三次」,因此我们可以根 据所有数的「某⼀个⽐特位」的总和 %3 的结果,快速定位到 ret 的「⼀个⽐特位上」的值是 0 还是 1 。 这样,我们通过 ret 的每⼀个⽐特位上的值,就可以将 ret 给还原出来。
class Solution {
public:
int singleNumber(vector<int>& nums) {
int ret=0;//目标值
for(int i=0;i<32;i++)
{
int sum=0;
for(auto x:nums)
{
if(x>>i&1)
{
sum++;
}
}//每个比特位逐次累加
sum%=3;
if(sum==1)
{
ret|=1<<i;
}
}//循环32次确定ret每一个比特位的值
return ret;
}
};给定数组,范围为[1,n],但里面缺失了两个数字,要求返回这两个缺失数字,返回顺序不做要求。
在消失的数字中,我们采用两轮异或的方式,即可直接求出,而本题有两个缺失的数字,我们又该如何处理呢?
class Solution {
public:
vector<int> missingTwo(vector<int>& nums) {
int n=nums.size();
int sum=0;
for(auto e:nums)
{
sum^=e;
}
for(int i=1;i<=n+2;i++)
{
sum^=i;
}//两轮异或之后sum即为缺失数字a与b异或的结果
int diff=0;
while(1)
{
if(sum>>diff&1)
{
break;
}
else
diff++;
}//寻找a和b比特位不同的位置
int a=0,b=0;
for(auto e:nums)
{
if(e>>diff&1)
{
a^=e;
}
else
{
b^=e;
}
}
for(int i=1;i<=n+2;i++)
{
if(i>>diff&1)
{
a^=i;
}
else
{
b^=i;
}
}//逐次异或
return {a,b};
}
};位运算在计算机科学中扮演着举足轻重的角色,它不仅以其高效和简洁让代码更具性能优势,还通过独特的逻辑体现了数学与工程的完美融合。在学习与实践中,善于发现和利用位运算的特性,能够让算法设计更加优雅,也能更深刻地理解计算机的底层逻辑。
“数尽千般妙,唯有位运藏。” 让我们以这一句诗作结,致敬位运算的奇妙世界。
关于位运算的介绍就暂告段落啦,希望能对大家的学习产生帮助,欢迎各位佬前来支持斧正!!!