一个数组,除了三个数唯一出现外,其它数均成对出现,求这三个数

本文介绍了一种算法,用于从一组整数中找到出现一次的三个数,其余的数都出现两次。算法通过位运算实现,适用于需要高效处理大量数据的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<pre name="code" class="cpp">// 有三个数出现一次,其他均出现两次,找出这三个数.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#define BIT_SIZE 32
#define isON(n, i) ((n)&1<<(i))

// 0x0111
// 0x1011
// 0x1100

// 0x0101
// 0x1001
// 0x1011


void findNumber2(unsigned int *arr, int size, unsigned int &A, unsigned int &B, unsigned int &C)
{
	int tempA, tempB;
	int countA, countB;
	int firstNum;
	int secondNum;
	int thirdNum;

	int findNumIdx = 0;
	int findArray[3] = {0};

	int i, j;

	for (i = 0; i < BIT_SIZE; i++)
	{	
		int tempA  = 0, tempB  = 0;
		int countA = 0, countB = 0;

		for (j = 0; j < size; j++)
		{
			if (isON(arr[j],i))
			{
				countA++;
				tempA ^= arr[j];
			}
			else
			{
				countB++;
				tempB ^= arr[j];
			}
		}

		if (countA & 0x1)
		{
			//bit i 出现了 基数次
			if (tempB != 0)
			{
				//如果三个只出现一次的数的第i位都是ON,那么tempB必定为0
				//如果三个只出现一次的数中有两个第i位为On,那么countA为基数就不成立
				//如果三个只出现一次的数中只有一个第i位为On,那么另外两个只出现一次的数的异或必定不为0
				firstNum = tempA;
				break;
			}
		}
		else
		{
			//bit i 出现了 偶数次
			if (tempB != 0 && abs(countA-countB)<3)
			{
				// 这 3 个数中的一个没有出现这个这个 bit i, 因此这个 tempB 就是不包含这个 bit i 的 3 个数中的其中一个
				//如果三个只出现一次的数中有两个的第i位为On,那么tempB(如果tempB不为0)就是那一个第i位不为On的那个数
				//如果三个只出现一次的数没有一个的第i位为On,那么tempB
				firstNum = tempB;
				break;
			}
		}
	}


	unsigned int merged = 0;

	for (int idx = 0; idx < size; idx++)
	{
		merged ^= arr[idx];
	}

	merged ^= firstNum;
	
	secondNum = 0;

	for (int k = 0; k < BIT_SIZE; k++)
	{
		if (isON(merged, k))
		{
			for (int m = 0; m < size; m++)
			{
				if ((arr[m] != firstNum) && isON(arr[m], k))
				{
					secondNum ^= arr[m];
				}
			}
			break;
		}
	}

	thirdNum = merged ^= secondNum;

	A = firstNum;
	B = secondNum;
	C = thirdNum;
}


int _tmain(int argc, _TCHAR* argv[])
{
	unsigned int Array[] = {2,2,4,4,8,8,13,13,10,10,5,0,11};

	unsigned int a, b, c;

	findNumber2(Array, 13, a, b, c);

	return 0;
}




                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值