您的位置:首页 > 其它

从2.5亿个数字里面找出不重复的数字的个数

2007-10-22 15:50 253 查看
整理自:http://topic.csdn.net/u/20070929/14/b183cd03-d780-4c59-a666-ab127f12f7b1.html

问题描述如下:
有2.5亿个整数(这2.5亿个整数存储在一个数组里面,至于数组是放在外存还是内存,没有进一步具体说明);
要求找出这2.5亿个数字里面,不重复的数字的个数(那些只出现一次的数字的数目)
另外,可用的内存限定为600M;
要求算法尽量高效,最优;

1. caoxic的算法
BYTE marks[2^29];//512M // BYTE marks[2^32/8]; //用这个就更清楚了,标志所有整数(2^32)出现的可能
BYTE repmarks[2^25];//32M 32M*8>2.5亿 //标志2.5亿个数字数组里面的数字是否重复过
const BYTE bitmarks[8]={1,2,4,8,16,32,64,128};
DWORD CalcDifNum(DWORD *pBuf,DWORD bufcount)
{
DWORD dw ;
DWORD count = 0 ;// 不重复的数字(包括出现多次的数字,只算一个)的个数,例子:1 2 2 3 5 3 4 算5个
DWORD count2 = 0 ;//重复出现的数字的个数,例子:1 2 2 3 5 3 4 算2个
memset(marks,0,sizeof(marks));
memset(repmarks,0,sizeof(repmarks));
ASSERT(sizeof(repmarks)*8>=bufcount);//断言repmarks数组够用
for(dw=0;dw<bufcount;dw++)
{
if(marks[pBuf[dw]>>3]&bitmarks[pBuf[dw]&7])
{
repmarks[dw>>3] |= bitmarks[dw&7];//标志pBuf[dw]这个数字出现重复
}
else
{
count ++;
marks[pBuf[dw]>>3] |= bitmarks[pBuf[dw]&7];//标志pBuf[dw]这个数字出现
}
}

memset(marks,0,sizeof(marks));
for(dw=0;dw<bufcount;dw++)
{
if(repmarks[dw>>3] & bitmarks[dw&7])//
{
if(marks[pBuf[dw]>>3]&bitmarks[pBuf[dw]&7])
{
}
else
{
count2 ++; //重复的数字的数量
marks[pBuf[dw]>>3] |= bitmarks[pBuf[dw]&7];
}
}
}
return count-count2;
}

2. 改一下,应该也可以:

BYTE marks[2^29];//512M // BYTE marks[2^32/8]; //用这个就更清楚了,标志所有整数(2^32)出现的可能
BYTE repmarks[2^25];//32M 32M*8>2.5亿 //标志2.5亿个数字数组里面的数字是否重复过
const BYTE bitmarks[8]={1,2,4,8,16,32,64,128};
DWORD CalcDifNum(DWORD *pBuf,DWORD bufcount)
{
DWORD dw ;
DWORD count = 0 ;// 不重复的数字(包括出现多次的数字,只算一个)的个数,例子:1 2 2 3 5 3 4 算5个
DWORD count2 = 0 ;//只出现一次数字的个数,例子:1 2 2 3 5 3 4 算3个
memset(marks,0,sizeof(marks));
memset(repmarks,0,sizeof(repmarks));
ASSERT(sizeof(repmarks)*8>=bufcount);//断言repmarks数组够用
for(dw=0;dw<bufcount;dw++)
{
if(marks[pBuf[dw]>>3]&bitmarks[pBuf[dw]&7])
{
repmarks[dw>>3] |= bitmarks[dw&7];//标志pBuf[dw]这个数字出现重复
}
else
{
count ++;
marks[pBuf[dw]>>3] |= bitmarks[pBuf[dw]&7];//标志pBuf[dw]这个数字出现
}
}

for(dw=0;dw<bufcount;dw++)
{
if(!(repmarks[dw>>3] & bitmarks[dw&7]))//非重复的位置
{
count2 ++; //只出现一次的数字的数量
}
}
return count2;
}

3. 把数组里面的数字分两类,正数负数,marks数组分成两部分标志,1.该数已经标志[0 --> 2^28-1] 2.标识该数已经重复[2^28 -->2^29-1]。

BYTE marks[2^29];//512M // BYTE marks[2^32/8]; //用这个就更清楚了,标志所有整数(2^32)出现的可能
const BYTE bitmarks[8]={1,2,4,8,16,32,64,128};
DWORD CalcDifNum(DWORD *pBuf,DWORD bufcount)
{
DWORD dw ;
DWORD count = 0 ;// 不重复的数字(包括出现多次的数字,只算一个)的个数,例子:1 2 2 3 5 3 4 算5个
DWORD count2 = 0 ;//重复出现的数字的个数,例子:1 2 2 3 5 3 4 算2个
memset(marks,0,sizeof(marks));
for(dw=0;dw<bufcount;dw++)
{
if(pBuf[dw]>=0)
{
if(marks[pBuf[dw]>>3]&bitmarks[pBuf[dw]&7])
{
if(marks[2^28+pBuf[dw]>>3]&bitmarks[pBuf[dw]&7])
{

}else
{
marks[2^28+pBuf[dw]>>3] |= bitmarks[pBuf[dw]&7];//标志pBuf[dw]这个数字出现重复
count2 ++;
}
}
else
{
count ++;
marks[pBuf[dw]>>3] |= bitmarks[pBuf[dw]&7];//标志pBuf[dw]这个数字出现
}
}
}

memset(marks,0,sizeof(marks));
for(dw=0;dw<bufcount;dw++)
{
if(pBuf[dw]<0)
{
pBuf[dw] = -pBuf[dw];
if(marks[pBuf[dw]>>3]&bitmarks[pBuf[dw]&7])
{
if(marks[2^28+pBuf[dw]>>3]&bitmarks[pBuf[dw]&7])
{

}else
{
marks[2^28+pBuf[dw]>>3] |= bitmarks[pBuf[dw]&7];//标志pBuf[dw]这个数字出现重复
count2 ++;
}
}
else
{
count ++;
marks[pBuf[dw]>>3] |= bitmarks[pBuf[dw]&7];//标志pBuf[dw]这个数字出现
}
}
}

return count-count2;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐