引子:我们在之前的案子中破解过基础的单身狗问题,那面对更有挑战的案子,且看李先生如何破局,那下凶手!
复习:
1,位操作符:
正整数原,反,补码都相同
首位是符号位
原码也可以用补码+1表示
计算机中用的是补码
左移<<:左边抛弃,右边补0;
右移>>:逻辑右移和算数右移
按位与&:有0就为0,全1才为1;
按位或|:只要友谊就位1,全为0才为0;
按位异或^:相同为0,不相同为1;
按位取反~:1为0,0为1;
逗号表达式:从左向右依次执行,整个表达式是最后一个表达式的结果!
2,找出唯一的数字(利用异或的作用)
int value=0;
for(auto e:nums)
{value^=e;}
3,应用
一,不加临时变量进行交换
int a=0; int b=12;
a=a^b; b=a^b; a=a^b;
二,求一个整数存储在内存中二进制一的个数
int n=15; int conunt=0;
while(n) n=n&(n-1); count++;
三,按位与
a&1==1;说明a的二进制最低位是1;
a&1==0;说明a的二进制最低位是0;
四,判断是否为偶数
if(n=n&(n-1)==0)
{cout<<"yes"<<endl;}
场景复现:(力扣)
一:
给你一个整数数组 nums
,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。你必须设计并实现线性时间复杂度的算法且仅使用常量额外空间来解决此问题
二:
给你一个整数数组 nums
,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。你必须设计并实现线性时间复杂度的算法且使用常数级空间来解决此问题。
题解:
对于场景一:
思路: 我们先用异或筛选出那二个只出现过一次的异或值,记为x, 然后用分组思想,我们可以使用位运算 x & -x取出 x 的二进制表示中最低位那个 1 ,注意在(C语言中,-x实现是用取反+1实现),那我们就可以知道在这个位置,我们要找的这二个数的二进值不同,一个是0,一个是1,所以我们就可以用这个位置的一进行分组,可以分成二组!在进行分别全员异或找到这二个值,那就解出来了!
代码:
class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
unsigned int value=0;
for(auto e:nums)
{
value^=e;
}
int peat=value&(-value);
int h1=0,h2=0;
for(auto e:nums)
{
if(e&peat)
{
h1^=e;
}
else{
h2^=e;
}
}
return{h1,h2};//采用了匿名构造函数
}
};
结果:
对于场景二:
思路:所求的数字第 i 个二进制位就是数组中所有元素的第 i 个二进制位之和除以 3的余数
自己琢磨琢磨!
class Solution {
public:
int singleNumber(vector<int>& nums) {
int value=0;
for(int i=0;i<32;i++)
{
int sum=0;
for(auto e:nums)
{
sum+=((e>>i)&1);
}
if(sum%3)
{
value|=(1<<i);
}
}
return value;
}
};