【面试题】位图

位图

给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数

中。【腾讯】

  1. 遍历,时间复杂度O(N)
  2. 排序(O(NlogN)),利用二分查找: logN

申请512M的内存

一个bit位代表一个unsigned int值

读入40亿个数,设置相应的bit位

读入要查询的数,查看相应bit位是否为1,为1表示存在,为0表示不存在

我们可以用每一个二进制位来记录一个数据,一个int本来只能记录一个数据的,现在可以记录64个数字了,大大减少的空间。

在小端存储的机器上是这样存储的:数据高字节保存在内存的高地址中,数据的低字节保存在低地址中。

比如我要把19记录进去

19/8=2

19%8=3

从0开始算,原本19/8=2,因此是在第三个字节当中,第3个位置(位置从0开始算)。

如何添加数据

如果我要把6这个数据添加到位图当中,初始化的位图的状态是全0。

如下图所示(位图的初始状态):

0 0 0 0 0 0 0 0

6/8=0;

6%8=6;

因此就是在第0个字节中第6个位置。

可以构造出一个如下的二进制序列

0 1 0 0 0 0 0 0

将两个二进制序列**按位或(|)**一下,0|1=1,0|0=0,不会对其他位置的数据造成改变。

那么如何进行构造呢?

只要将1左移(<<)j个位置即可1<<j

如何删除数据

如果我要把6这个数据从位图当中删除

6/8=0;

6%8=6;

因此就是在第0个字节中第6个位置。

如下图所示(位图的初始状态):

0 1 0 0 0 0 0 0

可以构造出一个如下的二进制序列

1 0 1 1 1 1 1 1

将两个二进制序列**按位与(&)**一下,0&1=0,0&0=0,1&1=1,不会对其他位置的数据造成改变。

那么如何进行构造呢?

只要将1左移(<<)j个位置然后按位取反即可~(1<<j)

代码实现

namespace mudan
{
   
	template<size_t N>
	class bitset
	{
   
	public:

		bitset()
		{
   
			_bits.resize(N / 8 + 1, 0);//计算出需要多少字节来存储
		}

		void set(size_t x)
		{
   
			size_t i = x / 8
评论 30
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值