如果常规的想法是给这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即unsigned int 最大数/32(注:>>5 即除以2^5=32)
}
//位置(置1)
void Set(unsigned int num)
{
size_t index = num >>5;//确定是第几个整数,因为一个整数表示32个数
size_t pos = num % 32;//确定在哪个位
_a[index] |= (1<< pos);//将1向左移动pos位找到该数,即该数置1,再进行或运行,对该整数
该位置1
}
//位置清0(置0)
void ReSet(unsigned int num)
{
size_t index = num >> 5;//确定是第几个整数
size_t pos = num % 32;//确定在那个位
//表示该位置的数不存在
_a[index] &= ~(1 << pos);//置0
}
//判断是否存在
bool Test(unsigned int num)
{
size_t index = num >> 5;//算整数
size_t pos = num % 32;//算位置
//为1表示存在,为0表示不存在
return _a[index] &= (1 << pos);
}
protected:
vector<int>_a;
};
int main()
{
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;
return 0;
}
那么如何给一个数置1还是清0呢?
我们知道-1在计算机是按照补码的方式存储,为全1;11111111 11111111 11111111 11111111,转换成无符号的整形就是2^32-1,这样就可以存储整形里面所有的数字了。
加强版:
给定一个100亿的数,设计算法找到只出现一次的整数;
这个也是一个大数存储的问题,和前面一样按照常规的存储内存肯定放不下,但是如果按照位图的方式存储,大约需要1.25G的内存计算机可以容纳.
但是此时的状态有三种:
a:不存在
b:出现一次
c:出现多次
如果有一个位的话只能表示2种状态,为了解决这个问题我们可以用2个位来表示状态,这样就可以表示多种状态,0表示不存在,1表示出现一次,2或者3表示出现多次,这样就可以快速判断只出现一次的整数。
————————————————
版权声明:本文为CSDN博主「f2016913」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/f2016913/article/details/70553164