原文:https://blog.csdn.net/deaidai/article/details/78167367
位运算基础
& 按位与
如果两个相应的二进制位都为1,则该位的结果值为1,否则为0
| 按位或
两个相应的二进制位中只要有一个为1,该位的结果值为1
^ 按位异或
若参加运算的两个二进制位值相同则为0,否则为1 ~ 取反 ~是一元运算符,用来对一个二进制数按位取反,即将0变1,将1
左移
用来将一个数的各二进制位全部左移N位,右补0
右移
将一个数的各二进制位右移N位,移到右端的低位被舍弃,对于无符号数, 高位补0
原理:
a ^b ^b=a
x&(-x)取x转换为二进制时的最右的1
问题
数组中,只有一个数出现一次,剩下都出现两次,找出出现一次的数。
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
int i;
int a[100];
int b=0;
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
b^=a[i];
}
printf("%d",b);
return 0;
}
数组中,只有两个数出现一次,剩下都出现两次,找出出现一次的
#include <stdio.h>
int last(int i)
{
return i&(-i);
}
int main()
{
int n;
scanf("%d",&n);
int i;
int a[100];
int res=0;
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
res^=a[i];
}
int l=last(res);
int b[2]={0};
for(i=0;i<n;i++)
{
if((a[i]&l)==0)b[0]^=a[i];//注意啊a[i]&l要有括号
else b[1]^=a[i];
}
printf("%d %d",b[0],b[1]);
return 0;
}
找出数组中唯一出现一次的数,其它数都出现了三次
一个数从二进制的角度来看,无非就是0和1,若是我们只从各个位来看,就把这一位的内容加起来,除以3,剩余的余数就是单独剩下的这个数在这一位上的值。
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
int i;
int a[100]={0};
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
int b[32]={0};//32位足以储存数据
int j;
int result=0;
for(i=0;i<32;i++)
{
for(j=0;j<n;j++)
{
b[i]+=(a[j]>>i)&1;//将每一个a的数据的第j位加到b中,&1时为了将其他位清零
}
result |=(b[i]%3)<<i;//将第j位数字复原,|的作用是两个相应的
} 二进制位中只要有一个为1,该位的结果值为1
printf("%d",result);
return 0;
}