IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 5.【C语言】102个整数中有50个数出现了两次,2个数出现了一次, 找出出现了一次的那两个数 -> 正文阅读

[C++知识库]5.【C语言】102个整数中有50个数出现了两次,2个数出现了一次, 找出出现了一次的那两个数

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

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

算法思想:

考察分堆的思想

step1:先将所有的数异或,得到异或后的结果num

step2:找出最低位为一的那一个数result

step3:将所有的数与分割值result按位与,就会把原有的数分为俩堆

step4:分开后对各自的那一堆进行异或,得到那个单独的数

(1)对于用num与一组数:3,2,5,8,6,5,2,3 依次按位异或的意义可以参照

4.【C语言】101个整数中有50个数出现了两次,1个数出现了一次, 找出出现了一次的那个数

而在这组102个数中,有50个数字成对出现,还有两个单独出现。则逐个按位与后得到num=14,这个结果也为 8 和 6 按位异或的结果。
(2)此时需要找到一个数值result将这组数分成两堆,每一个堆出现一个单独的数。然后在对每个堆中的元素进行一次按位异或操作,最后得到两个独立的数。
我们来理解计算得到result的意义:

8? ? ? ? 0000 1000????????????????????????????????????????????????

6? ? ? ? 0000 0110? ? ? ? ^

14? ? ? 0000 1110? ? ? ? num?????????

可以看到如果num的某一位出现1,必然是两个数对应的相同比特位,一个为1,另一个为0,异或得到的。所以取num中某一位为1,其余位为0,组成result。通常取result从右往左数最低位为1,其余位为0的数。如:num = 0000 1110,则取 result = 0000 0010 。???????

得到result通常有两个方法:

(1)? result = num&-num

(2) 令 i=1,利用循环寻找num&i != 0 的 i?值,如果一直运算为0,则 i 不断按位左移,直到运算得1。

while((num & i)== 0)

? ? ? ? a<<1;

?则通过result=0000 0010 必然能将这组数分成两堆。例如result与6进行按位与得到1;result与8进行按位与得到0,而result与其他数按位与也会得到1和0两种情况。
(3)用result依次和每一个数进行按位与,就会遇到结果为0和1。结果为1的arr[i]和first进行按位异或;结果为0的arr[i]和second进行按位异或。最后会得到两个出现1次的数:first和second。

代码如下:

#include<stdio.h>

int main()
{
	int arr[8] = { 3,2,5,8,6,5,2,3 };
	int i, result,num=0;
	int first=0, second=0;
	//1.先将所有的数异或,得到异或后的结果num
	for (i = 0; i < sizeof(arr) / sizeof(int); i++) {
		num ^= arr[i];
	}
	//2.找出最低位为一的那一个数result
	result = num & -num;
	for ( i = 0; i < sizeof(arr) / sizeof(int); i++)
	{
		//3.将所有的数与result按位与,就会把原有的数分为俩堆
		if (result&arr[i])
		{
			//4.分开后对各自的那一堆进行异或,得到那个单独的数
			first ^= arr[i];
		}
		else 
		{
			second ^= arr[i];
		}
	}
	printf("%d %d\n", first, second);

	return 0;
}

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-18 12:31:35  更:2021-08-18 12:33:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 12:15:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码