问题描述是这样的:
在一个文件中存放有100亿个整数,每个整数都是32位,因为32位整数最多表示40亿,所以其中一定有重复出现的数。快速找到这样的任意一个数即可。
思路如下:
32个bit可以分为两段,高16bit看做前缀,那么这其中至少有一个前缀一定出现超过2^16次,否则的话就没有重复的数了。那么我们就先把出现次数超过2^16次方
的前缀找出来。然后遍历文件中的所有数,统计拥有该前缀的数的低16位是否重复出现过。只要重复出现过,那么这个数就是我们要找的数。
代码如下:
int iPrefix[1 << 16];
memset(&iPrefix, 0, sizeof(iPrefix));
unsigned int iNum = 0;
unsigned int iDupPrefix = 0;
//从头开始遍历所有的数,找到有重复数的前缀,放到iDupPrefix
while(GetOneNum(&iDupPrefix ) >= 0)
{
<span style="white-space:pre"> </span>iDupPrefix >>= 16;
<span style="white-space: pre;"> </span>iPrefix[iDupPrefix ]++;
<span style="white-space: pre;"> </span>if(iPrefix[iDupPrefix ] > (1 << 16))
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>break;
<span style="white-space:pre"> </span>}
}
iDupPrefix <<= 16;
memset(iPrefix, 0, sizeof(iPrefix));
//遍历以iDupPrefix为前缀的数,找到重复数
while(GetOneNum(&<span style="font-family: Arial, Helvetica, sans-serif;">iNum</span>) >= 0)
{
iNum ^= iDupPrefix;
if (iNum < (1 << 16))
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>iPrefix[iDupPrefix ]++;
<span style="white-space:pre"> </span>if(iPrefix[iDupPrefix ] > (1 << 16))
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> printf("find number:%u", iNum);</span>
<span style="white-space:pre"> </span>break;
<span style="white-space:pre"> </span>}
}