bitset
1.给40亿个不重复的无符号整数,没排过序,给一个无符号整数,如何快速判断一个数是否在这40亿个中
①.如果用排序加二分查找,40亿个数需要16g内存,内存开不出这么大连续空间
②.每个值映射一个比特位,需要开多少个比特位?并非40亿个,而是2^32个(42亿9千万),开空间开的不是数据个数,而是数据范围
0.5g
采用位图解决
数据是否在给定的整型数据中,结果是在或者不在,刚好是两种状态,那么可以使用一个二进制比特位来代表数据是否存在的信息,如果二进制比特位为1,代表存在,如果为0,代表不存在
模拟实现位图
template<size_t N>
class bitset{
public:
bitset(){
bits.resize(N/32+1,0);
}
void set(size_t x){
size_t i=x/32;
size_t j=x%32;
bits[i]|=(1<<j);
}
void reset(size_t x){
size_t i=x/32;
size_t j=x%32;
bits[i]&=~(1<<j);
}
bool test(size_t x){
size_t i=x/32;
size_t j=x%32;
return bits[i]&(1<<j);
}
private:
vector<int>bits;
};
2.给定100亿个整数,设计算法找到只出现一次的整数
我们分三种情况讨论
出现0次 00
出现1次 0 1
出现两次及以上 1 0
我们考虑使用两个位图
template<size_t N>
class twobitset{
public:
bool set(size_t x){
if(bs1.test(x)==false&&bs2.test(x)==false){
bs1.set(x);
}
else if(bs1.test(x)==false&&bs2.test(y)==true){
bs1.set(x);
bs2.reset(x);
}
}
private:
bitset<N>bs1;
bitset<N>bs2;
};
3.设计算法超出出现次数不超过2次的所有整数
出现0次 0 0
出现1次 0 1
出现2次 1 0
出现3次及以上1 1
template<size_t N>
class twobitset{
public:
bool set(size_t x){
if(bs1.test(x)==false&&bs2.test(x)==false){
bs1.set(x);
}
else if(bs1.test(x)==false&&bs2.test(x)==true){
bs1.set(x);
bs2.reset(x);
}
else if(bs1.test(x)==true&&bs2.test(x)==false){
bs2.set(x);
}
}
private:
bitset<N>bs1;
bitset<N>bs2;
};
4.给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集
各自映射到一个位图,如果一个值在两个位图都存在,则是交集
template <size_t N> class bitset;
operator[]
#include<bitset>
#include<iostream>
using namespace std;
int main(){
bitset<4>foo; //0000
foo[1]=1; //将第一位设为1 0010
foo[2]=foo[1]; //将第二位设为1 0110
cout<<foo.test(2)<<endl;//因为已经将2这一位设为1,所以test(2)为true
cout<<foo[3]<<endl;//3这一位没被设置,故为0
cout<<foo<<endl;
}
count(返回已经被set的个数)
any
none
all
flip