42亿QQ,O(1)时间复杂度完成查找

一、问题描述:

  1.在42亿个qq号码中,如何使用O(1)时间复杂度去查找一个QQ号是否存在。

  2.qq号的位数小于13位,存储着42亿QQ号的内存不得超过600MB.

二、位图排序思想

  由于待排序的数据记录较多,我们单纯地使用常见的排序方法时间效率较低,运行时间会很长。而且内存空间有限(限制为1MB左右),所以我们不能同时把所有整数读入内存(如果每个整数使用7个字节来存储,那么1MB内存空间只能存大约143000个数字)。当然我们可以多次读取输入文件,多次排序,但是更好的方案是使用位图排序,可以使用有限的1MB内存空间并只进行一趟排序。

      1.根据待排序集合中最大的数,开辟一个位数组,用来表示待排序集合中的整数;

      2.待排序集合中的数字在位数组中的对应位置置1,其他的置0;

      例如,待排序集合{1,2,3,5,8,13}可以表示为:0-1-1-1-0-1-0-0-1-0-0-0-0-1

      这样排序过程自然可以分为三步:

      第一步:将所有的位都置为0;

      第二步:通过读入文件中的每个整数,将每个对应的位都置为1;

      第三步:检验每一位,如果该位为1,输出对应的整数。

      注意:位图排序是使用一个二进制位而不是一个整数来表示0或1,这样可以大大地减少所需要的内存空间。使用位图排序的前提是要知道待排序序列中的最大数。位图排序的缺点是有些数没有出现过,仍要为其保留一个位。故位图排序比较适合关键字密集的序列,例如一个QQ号码。

/*Phase 1: initialize set to empty*/

  for
i = [0, n)

    bit[i] = 0

/*Phase 2: insert present elements into the set*/

  for
each i in the input file

    bit[i] = 1

/*Phase 3: write sorted output*/

  for
i = [0, n)

    if
bit[i] == 1

      write i on the output file

三、使用位图排序的方法

      位图排序时,我们需要考虑:给出一个数,如何找到其对应位图的位置,方法就是首先找到该数对应的字节,然后在找到该数对应的位。例如一个QQ号是:983262245,则将bit的98326625位进行标记。bitset是C++提供的一种位集合的数据结构,它让我们可以像使用数组一样使用位,可以访问指定下标的bit位。因此将通过bitset容器进行存储42个qq号码。由于一个字节可以存放8个QQ号码,则4200000000/8/1014/1024 = 500.679Mb,内存合适,通过bit位下表来判断QQ号码是否存在。

#include<iostream>
#include<bitset>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const unsigned int MAX = 4200000010;
typedef unsigned int UT;
bitset<MAX> bit;
int main(){
	//开始存储QQ
	for(UT i=1;i<10;i++){
		UT qq;
		printf("请输入第%d个QQ号:",i);
		scanf("%d",&qq); 
		bit.set(qq);
	} 
	UT qq;
	printf("请输入:");
	while(scanf("%d",&qq)!=0){
			
		if(bit.test(qq)){
			printf("Yes\n");
		}
		printf("请输入:");
	}
	return 0;
} 

存储:空间占用大约500Mb

查找:时间复杂度为O(1)

通过位排序的方法,在实现内存内,实现在O(1)时间复杂度内进行一个QQ号码的查找。



  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值