“因为我害怕结束,所以拒绝了所有的开始。”


本篇是我遇到的有关二进制题目的综合整理,欢迎大家讨论留言。。。

1.交换两个变量(不创建临时变量)

题目内容:
不允许创建临时变量,交换两个整数的内容

方法:
a ^ a = 0;
0 ^ a = a;

    int main()
    {
        int a = 10;
        int b = 5;
        a = a ^ b;
        b = a ^ b;//此时相当于b = a ^ b ^ b(替换a);即b = a
        a = a ^ b;//此时相当于a = a ^ b ^ a;即a = b
        printf("a = %d\n", a);
        printf("b = %d\n", b);
        return 0;
    }

结果:
在这里插入图片描述

2.统计二进制中1的个数

题目内容:
写一个函数返回参数二进制中 1 的个数。

比如: 15 0000 1111 4 个 1
牛客网OJ链接

方法:
n = n & (n - 1)
每次去掉二进制中最右边的1

int main()
{
    int a = 5;//转换为二进制为00000000000000000000000000000101
    int count = 0;
    while (a)
    {
        a = a & (a - 1);
        count++;
    }
    printf("%d\n", count);
    return 0;
}

结果:
在这里插入图片描述

3.求两个数二进制中不同位的个数

题目内容:
编程实现:两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同?

输入例子:

1999 2299

输出例子:7
牛客网OJ链接

方法:
求二进制位不同联想到 ^ :
^的逻辑规则:
相同为0,相异为1;

int main() 
{
    int a, b;
    while (scanf("%d %d", &a, &b) != EOF) { // 注意 while 处理多个 case
        // 64 位输出请用 printf("%lld") to 
       int c = 0;
       int count = 0;
       c = a ^ b;
       while(c)
       {
        c = c & (c - 1);
        count++;
       }
       printf("%d\n",count);
    }
    return 0;
}

4.单身狗1

题目内容:
在一个整型数组中,只有一个数字出现一次,其他数组都是成对出现的,请找出那个只出现一次的数字。

例如:

数组中有:1 2 3 4 5 1 2 3 4,只有5出现一次,其他数字都出现2次,找出5

方法:
0 ^ a = a;
a ^ a = 0;

#include <stdio.h>

int find_single_dog(int arr[], int sz)
{
    int ret = 0;
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        ret ^= arr[i];
    }
    return ret;
}
int main()
{
    int arr[] = { 1,2,3,4,5,1,2,3,4 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    int dog = find_single_dog(arr, sz);
    printf("%d\n", dog);
    return 0;
}

5.打印整数二进制的奇数位和偶数位

题目内容:
获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列

方法:
一个整数32个比特位,分别按照顺序右移,然后进行打印。

  1. 提取所有的奇数位,如果该位是1,输出1,是0则输出0
  2. 以同样的方式提取偶数位置
    检测num中某一位是0还是1的方式:
    1. 将num向右移动i位
    2. 将移完位之后的结果与1按位与,如果:
      结果是0,则第i个比特位是0
      结果是非0,则第i个比特位是1
void Printbit(int num)
{
	for(int i=31; i>=1; i-=2)
	{
		printf("%d ", (num>>i)&1);
	}
	printf("\n");
    
	for(int i=30; i>=0; i-=2)
	{
		printf("%d ", (num>>i)&1);
	}
	printf("\n");
}

6.找单身狗2

题目内容:
一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。

编写一个函数找出这两个只出现一次的数字。

例如:

有数组的元素是:1,2,3,4,5,1,2,3,4,6

只有5和6只出现1次,要找出5和6.

方法:
找出一个只出现过一次的数字的问题处理方法就是找一个数字把里面所有的数字都异或一遍,利用异或两次等于没异或的特点来处理。那么如果有两个数字都只出现了一次,那么如此得到的应该是两个数异或的结果。首先这个结果肯定不是0(要不然就全都配对了),所以里面一定至少一位是一。找出值为1的一位,以这一位的值将结果分为两组。例如1 2 3 4 1 2,异或完的结果应该是3^4得到的111,那么随便找一位就行了。例如找最低位,那么这一位是1的有1 3 1,是0的有2 4 2,由于是利用异或结果为1的某一位分的组,所以两个待查询数字一定分别在两组中。所以再找两个变量,分别异或两组数,即可找到这两个数。

void findTwoNum(int arr[], int n, int * pnum1, int * pnum2)
{
 int i;
 int sum = 0;for (i = 0; i < 9; i++)
 {
  sum ^= arr[i];
 } //先找到两个数互相异或的结果int pos;
 for (i = 0; i < 32; i++)
 {
  if (sum & 1 << i)
  {
   pos = i;
   break;
  }
 } //再找到有分歧的一位。在这一位上,两个数一定是一个1一个0*pnum1 = *pnum2 = 0;
 for (i = 0; i < 10; i++)
 {
  if (arr[i] & 1 << pos)
  {
   *pnum1 ^= arr[i]; //这一位是1的,放在数1里
  }
  else
  {
   *pnum2 ^= arr[i]; //这一位是0的,放在数2里
  }
 }
}

7.交换奇偶位

题目内容:
写一个宏,可以将一个整数的二进制位的奇数位和偶数位交换。

方法:
分别取出二进制的奇数位和偶数位,然后 | 进行交换。
|的逻辑规则:
有1为1,全0才0.

在这里插入图片描述

交换奇偶位,需要先分别拿出奇偶位。既然是宏,分别拿出用循环不是很现实,那就用&这些位的方式来做。奇数位拿出,那就是要&上010101010101……,偶数位拿出,就是要&上101010101010……,对应十六进制分别是555……和aaa……,一般我们默认是32位整数,4位对应一位16进制就是8个5,8个a。通过& 0x55555555的方式拿出奇数位和& 0xaaaaaaa的方式拿出偶数位。奇数位左移一位就到了偶数位上,偶数位右移一位就到了奇数位上,最后两个数字或起来,就完成了交换。

※这个宏只能完成32位以内的整形,要想完成64位的,那就将5和a的数量翻倍即可。

#define SwapIntBit(n) (((n) & 0x55555555) << 1 | ((n) & 0xaaaaaaaa) >> 1)

完。。。

那么,微笑地与你就再见了,

把你留在街角,尽管频频回顾
你的不动的身影仍然会在暮色中逐渐模糊,
就算我一直不停地回头,一直不停地挥手,
总会在最后有一个转角将你遮住,
将我们从此隔绝,从那以后,就是离别了……

  • 20
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Filex;

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值