腾讯面试题:给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中?

1.腾讯面试题:给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中?

思想:用数组来存这40亿个数,而且只能用bit来表示。why?40亿约等于4G,就算你用一个字节来,也需要4GB,32位的机子爆掉了。如果用bit来存,意思一个字节就能表示8个数,这个样子只需要512M内存。这个属于接受范围。如果有内存要求,则可以分块。

如何用bit位表示某个数?下面以1为例。

  • 1/8=0,即存在数组的第0位。
  • 1%8=1,即存在数组第0位的char的第1位,将该位置为1。
在举个例子,12345。

  • 12345/8=1543,即数组的第1543位
  • 12345%8=1,即存在数组的第1543位的char的第1位,将该位置为1。
我们以16进制来表示char中每一位单独置为1的情况,即0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01。

如何判断将某一位置为1?

以将a[0]的第二位置为1为例,用位或。a[0]=a[0] | 0x20;

判断某一位是否置为1?

判断a[0]的第二位是否置为1,用位与,a[0] &0x20.如果置为1,返回非0,否则返回0.

  1. #include<iostream>  
  2. #include<string.h>  
  3. #include<fstream>  
  4. using namespace std;  
  5. void setBit(char *arr,unsigned int num);  
  6. int isSet(char *arr,unsigned int num);  
  7. unsigned char tag[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};  
  8. int main()  
  9. {  
  10.     char * arr=new char[5242880];//512M  
  11.     memset(arr,0,5242880);  
  12.     unsigned int num;  
  13.     fstream in("1.txt",ios::in);  
  14.     while(in>>num)  
  15.     {  
  16.         setBit(arr,num);  
  17.     }  
  18.     in.close();  
  19.     cout<<"初始化完毕..."<<endl;  
  20.     cout<<"请输入需要判断的数:";  
  21.     while(cin>>num)  
  22.     {  
  23.         if(isSet(arr,num)!=0x00)  
  24.         {  
  25.             cout<<num<<"在数组中"<<endl;  
  26.         }else  
  27.             cout<<num<<"不在数组中"<<endl;  
  28.     }  
  29.     delete[] arr;  
  30.     return 0;  
  31. }  
  32. /* 
  33. *功能:将num对应位置为1 
  34. */  
  35. void setBit(char *arr,unsigned int num)  
  36. {  
  37.     int loc=num/8;  
  38.     int remainder=num%8;  
  39.     arr[loc]=arr[loc] | tag[remainder];  
  40. }  
  41. /* 
  42. *功能:判断num对应位是否置为1? 
  43. */  
  44. int isSet(char *arr,unsigned int num)  
  45. {  
  46.     int loc=num/8;  
  47.     int remainder=num%8;  
  48.     return arr[loc] & tag[remainder];  
  49. }  
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值