如果常规的想法是给这40亿数,放到一个很大的数组中,快速排序,然后采用二分查找,来判断这个数是否存在;
但是计算机的内存就是4G,大小差不多刚好是2^32大约为42亿左右,一个整形4个字节,40亿数大约需要16G个字节,在现实基本不可能实现,那么该如何存储呢?
方法:位存储
一个整形32个位,16G个字节只需要500M就可以,然后设置比特位1表示这个数存在,0表示这个数不存在。
#include<vector>
using namespace std;
class BitSet
{
public:
BitSet(size_t range)
{
_a.resize((range >>5)+ 1);
}
//位置(置1)
void Set(int num)
{
size_t index = num >>5;//确定是第几个整数
size_t pos = num % 32;//确定在那个位
_a[index] |= (1<< pos);//置1
}
//位置清0(置0)
void ReSet(int num)
{
size_t index = num >> 5;//确定是第几个整数
size_t pos = num % 32;//确定在那个位
//表示该位置的数不存在
_a[index] &= ~(1 << pos);//置0
}
//判断是否存在
bool Test(int num)
{
size_t index = num >> 5;//算整数
size_t pos = num % 32;//算位置
//为1表示存在,为0表示不存在
return _a[index] &= (1 << pos);
}
protected:
vector<int>_a;
};
void Test()
{
BitSet bs(-1);
bs.Set(1);
bs.Set(8);
bs.Set(100);
cout << "bs?" << "bs.Set(1) " << endl;
cout << "bs?" << "bs.Set(8) " << endl;
cout << "bs?" << "bs.Set(100) " << endl;
cout << "bs?" << "bs.Test(1) " << endl;
cout << "bs?" << "bs.Test(1) " << endl;
cout << "bs?" << "bs.Test(1) " << endl;
}
那么如何给一个数置1还是清0呢?
我们知道-1在计算机是按照补码的方式存储,为全1;11111111 11111111 11111111 11111111,转换成无符号的整形就是2^32-1,这样就可以存储整形里面所有的数字了。
加强版:
给定一个100亿的数,设计算法找到只出现一次的整数;
这个也是一个大数存储的问题,和前面一样按照常规的存储内存肯定放不下,但是如果按照位图的方式存储,大约需要1.25G的内存计算机可以容纳.
但是此时的状态有三种:
a:不存在
b:出现一次
c:出现多次
如果有一个位的话只能表示2种状态,为了解决这个问题我们可以用2个位来表示状态,这样就可以表示多种状态,0表示不存在,1表示出现一次,2或者3表示出现多次,这样就可以快速判断只出现一次的整数。