一维数组中出现奇数次的数

这篇博客介绍了如何在给定的一组整数数组中,利用位异或操作找出唯一出现次数为奇数的数以及两个出现次数为奇数的数。通过位异或的性质,可以在O(N)的时间复杂度和O(1)的空间复杂度下解决这两个问题。示例代码分别演示了找到一个奇数次数元素和两个奇数次数元素的过程。
摘要由CSDN通过智能技术生成
* 问题:存在一组数
* 问题 a):这组数中只存在一个数出现的次数是奇数,其他数都是偶数,找到这个奇数
* 问题 b):这组数中存在两个数出现的次数是奇数,其他数都是偶数,找到这两个奇数
* 要求:时间复杂度O(N),空间复杂度O(1)
#include<iostream>
using namespace std;
//函数声明
void findOddNumber1(int arr[],int length);
void findOddNumber2(int arr[], int length);
//主函数
int main()
{
	/*
	* 问题:存在一组数
	* 问题 a):这组数中只存在一个数出现的次数是奇数,其他数都是偶数,找到这个奇数
	* 问题 b):这组数中存在两个数出现的次数是奇数,其他数都是偶数,找到这两个奇数
	* 要求:时间复杂度O(N),空间复杂度O(1)
	*/
	//问题a
	int a1[] = { 1,8,1,1,2,6,2,2,3,3,2,3,4,5,6,3,7,5,7,8,1};
	findOddNumber1(a1,sizeof(a1)/sizeof(a1[0]));
	//问题b
	int a2[] = { 1,1,1,1,2,2,2,2,3,3,3,3,4,5,6,7,8,5,6,7,8,6 };
	findOddNumber2(a2, sizeof(a2) / sizeof(a2[0]));

	return 0;
}
/*
* 函数名:findOddNumber1
* 函数列表:int arr[] 要寻找到数组, int length 数组的长度
* 函数功能:数组中存在一个数的个数是奇数,找到数组中的这个奇数
* 函数返回值:无
*/
void findOddNumber1(int arr[], int length)
{
	int eor = 0;
	for (int i = 0; i < length; i++)
	{
		// 位异或^:相同为0,不同为1
		eor ^= arr[i]; //位异或运算 规则:0^n=n,n^n = 0,n^m = m^n, x^z^c^z^c = z^z^c^c^x=x
	}
	cout << "问题a的答案是:"<< eor << endl;
}
/*
* 函数名:findOddNumber2
* 函数列表:int arr[] 要寻找到数组, int length 数组的长度
* 函数功能:数组中存在两个数的个数是奇数,找到数组中的这两个奇数
* 函数返回值:无
*/
void findOddNumber2(int arr[], int length)
{
	int eor = 0;
	for (int i = 0; i < length; i++)
	{
		// 位异或^:相同为0,不同为1
		eor ^= arr[i]; //位异或运算 规则:0^n=n,n^n = 0,n^m = m^n, x^z^c^z^c = z^z^c^c^x=x
	}
	//cout << eor << endl;//eor = odd1^odd2
	//这个式子求的是eor中最右边的1,只要找到一个两个不同的地方就可以把数组分为odd1组和odd2组,
	//再用问题a的方法就能找到一个数量为奇数的数
	//假如:eor = 011  ~eor+1 = 101   rightOne = 001 = 1
	int rightOne = eor & (~eor + 1);//& 位与运算:同为1才是1
	//cout << rightOne << endl;
	int eor_2 = 0,eor_3 = 0;
	for (int i = 0; i < length; i++)
	{
		if((arr[i] & rightOne) == rightOne) //通过rightOne将数组分为两组 一组存在rightOne,一组不存在rightOne
		{
			eor_2 ^= arr[i];
		}
	}
	eor_3 = eor ^ eor_2; // eor = odd1^odd2  eor_2 = odd1或者odd2, m^n^m = n 得到另一个数
	cout << "问题b的答案是:"<< eor_2 << "\t" << eor_3 << endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

czx鑫

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

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

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

打赏作者

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

抵扣说明:

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

余额充值