12. 【C语言】 102个整数中有50个数出现了两次,2个数出现了一次, 找出出现了一次的那2个数(2_task)

在解决问题前需要了解三个位运算知识:

  1. 任何一个数和0按位异或就是其自身。例如:3^0=0;0000 0011 ^ 0000 0000 = 0000 0011
  2. 任何一个数和其自身按位异或结果为0。例如:3^3=0;0000 0011 ^ 0000 0011 = 0000 0000
  3. 去某个数num的为1的最低位,其余位为0的数,代码可表示为
    num=num&(-num) 或 num=num&~(num-1)。例如:3&(-3)=2;0000 0011 & 1111 1101 = 0000 0001

算法思想:
(1)对于用num与一组数:7,5,2,8,4,3,12,6,7,5,2,8,4,3,依次按位异或的意义可以参照我以前发的一个帖子。
11. 【C语言】101个整数中,50个数出现了两次,1个数出现了一次, 找出出现了一次的那个数(2_task)
而在这组102个数中,有50个数字成对出现,还有两个单独出现。则逐个按位与后得到num=10,这个结果也为12 和6按位异或的结果。
(2)此时需要找到一个数值result可以将这组数分成两堆,每一个对出现一个单独的数。再每个堆对堆中元素一次按位异或,最后得到两个独立的数。
我们来理解计算得到result的意义:
在这里插入图片描述
则通过result=0000 0010 必然能将这组数分成两堆。例如result与12进行异或得到1;result与12进行异或得到0,而result与其他数异或也会得到为0和不为0两种情况。
(3)用result依次和每一个数进行按位与,就会遇到结果为0和1。结果为1的a[i]和num1进行按位异或;结果为0的a[i]和num1进行按位异或。最后会得到两个出现1次的数:num1和num2。

如下测试三种形式的案例效果:
(1)a[]={7,5,2,8,4,3,6,12,7,5,2,8,4,3},期望结果为:6 12
在这里插入图片描述
(1)a[]={7,5,2,8,4,3,6,0,7,5,2,8,4,3},期望结果为:6 0
在这里插入图片描述
该算法时间复杂度和空间复杂度均为O(n)

完整代码如下:

#include<stdio.h>
#include<stdlib.h>

#define N 14
int main()
{
	short num = 0;
	short num1 = 0, num2 = 0;
	short a[] = { 7,5,2,8,4,3,12,6,7,5,2,8,4,3 };
	for (int i = 0; i < N; i++)
	{
		num=num^a[i];
	}
	short result = num&(-1)*num;
	for (int i = 0; i < N; i++)
	{
		if (result&a[i])
			num1 = num1^a[i];
		else
			num2 = num2^a[i];
	}
	printf("%3d%3d\n", num1, num2);
	system("pause");
}
  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值