位运算之寻找数字

原文: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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值