找到丢失的数字

本文详细介绍了如何使用随机数生成技术,结合哈希散列原理,解决数组中元素顺序被打乱且存在一个未知元素被替换为-1的问题。通过自定义随机数函数和遍历数组计算总和,最终找出缺失的元素。

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

这也是我在网上看到的一个亚马逊题目:

一个数组中包含了0-99,但顺序被打乱,而且其中之一个数变成了-1,请找出这个数。

这道题目其实还是很简单的,只需求一次加减就可以轻易找出这个数值了。时间是O(N),空间是O(1)。

但还是要继续写测试程序,如何生成一个随机的数组包含0-99呢?最简单的就是用rand()函数取模100,若有冲突,则放到下一个槽,直到有位置放为止(和哈希散列地址冲突的其中一个解决方案类似。)不过rand()是伪随机,为了得到一个真正的随机数,我想起以前见过的一份代码,用CPU的嘀嗒数来当作随机数,就是类似像赌场里面的赌博机一样的原理。代码如下:

unsigned int MyRand()
{
	unsigned int iRand = 0;

	Sleep(0);

	__asm
	{
		rdtsc;
		mov iRand, eax;
	}

	return iRand;
}

rdtsc(read time stamp counter)就是获得CPU(很多人把CPU比作工厂,其实他更像一个时钟,不停的转,按周期执行指令)嘀嗒了多少下的指令,该指令会把64位嘀嗒数放入eax和edx寄存器中,eax放低位,edx放高位。因此我觉得edx随机性不是很高(测试后的确如此,毕竟是高位,在很短的时间内可能变化不会很大),就用了eax。同时为了加强随机性,因为程序势必每隔一定时间调用一次这个随机函数,可能会造成周期性的得到一组随机数据(测试后的确如此……),我在rdtsc指令之前,调用了sleep(0)强制切换线程出CPU,打乱CPU调度,减少获得一样的嘀嗒数的可能。

const int MAX_RANGE = 100;
void SetRandom(int * pArray, int iNumber, int i)
{
	unsigned int iIndex = (i + MyRand()) % MAX_RANGE;	

	if (-1 == pArray[iIndex])
	{
		pArray[iIndex] = iNumber;
	}
	else
	{
		int j = iIndex + 1;
		for (j = iIndex + 1; j < MAX_RANGE; ++j)
		{
			if (-1 == pArray[j])
			{
				pArray[j] = iNumber;
				break;
			}
		}
		if (MAX_RANGE == j)
		{
			for (unsigned int k = 0; k < iIndex; ++k)
			{
				if (-1 == pArray[k])
				{
					pArray[k] = iNumber;
					break;
				}
			}
		}
	}
}

int main()
{
	// 答案
	int iResult = MyRand() % MAX_RANGE;

	// 生成随机的数组
	int pArray[MAX_RANGE];
	for (int i = 0; i < MAX_RANGE; ++i)
	{
		pArray[i] = -1;
	}

	for (int i = 0; i < MAX_RANGE; ++i)
	{
		if (iResult == i)
		{
			SetRandom(pArray, -1,i);
		}
		else
		{
			SetRandom(pArray, i, i);
		}
	}

	// 开始寻找丢失的数字
	int iSum = 0;
	for (int i = 0; i < MAX_RANGE; ++i)
	{
		iSum += pArray[i];
	}

	int iMaskSum = 0;
	for (int i = 0; i < MAX_RANGE; ++i)
	{
		iMaskSum += i;
	}

	int iLost = iMaskSum - iSum - 1;
	if (iLost == iResult)
	{
		std::cout << iLost << " is lost! correct\n";
	}
	else
	{
		std::cout << iResult << "is lost, but it returned " << iLost << "! wrong\n";
	}
	

	getchar(); 


}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值