Data structures 如何使用位图存储电话号码?

Data structures 如何使用位图存储电话号码?,data-structures,bitmap,Data Structures,Bitmap,如何存储电话号码,以便有效地查询特定电话号码是否已被使用 这是一个采访问题,我提出了许多数据结构(树、trie、压缩trie、跳过列表、bloomfilter),但他正在寻找位图。如何使用位图存储电话号码?术语“位图”过载,有几种不同的含义。在这里,我想采访者可能指的是一个,一个编号为0,1,2,…,U的位数组。你可以用一个位向量来表示0,1,2,…,U范围内的一个数字,如下所示:如果索引I处的位是0,那么我在集合中不存在,如果索引I处的位是1,那么我在集合中存在。由于可以在时间O(1)中索引到

如何存储电话号码,以便有效地查询特定电话号码是否已被使用

这是一个采访问题,我提出了许多数据结构(树、trie、压缩trie、跳过列表、bloomfilter),但他正在寻找位图。如何使用位图存储电话号码?

术语“位图”过载,有几种不同的含义。在这里,我想采访者可能指的是一个,一个编号为0,1,2,…,U的位数组。你可以用一个位向量来表示0,1,2,…,U范围内的一个数字,如下所示:如果索引I处的位是0,那么我在集合中不存在,如果索引I处的位是1,那么我在集合中存在。由于可以在时间O(1)中索引到位向量并翻转位,因此插入元素、删除元素以及在集合中查找元素的运行时为O(1)

缺点是空间使用总是Θ(U),并且与集合中的元素数量无关。如果假设电话号码的长度为10位,则需要1000000000位=2500000000字节=2.5GB的空间来使用原始编码存储电话号码。如果您假设电话号码不能以0开头,则可以通过假装号码系统以100000000而不是0开头,从编码中删除100000000位


希望这有帮助

有趣的是,你没有提到哈希表。看起来哈希表或位图确实非常适合这种情况,它可能更节省空间,使用位图查找速度也会更快。就空间/时间性能而言,Trie/压缩Trie很可能都类似于哈希表。跳过列表和树可能有最差的性能。bloom过滤器实际上是哈希表和位图的交叉;它的主要目的是限制磁盘访问的数量,因此在这种情况下使用有限

如果位图包含超过大约
N/log(N)
已使用或未使用的元素,并且当未使用或已使用元素的哈希表已满一半时,位图在空间上通常比已使用或未使用元素的哈希表更好。从而节省了超过
log_2(N)/2
的空间*

例如,如果您使用10位数的电话号码,并且使用了一半的号码。大约需要
10^10位
。但是,在哈希表中存储
5x10^9个数字
,每个数字大约需要
32位
,因此总共需要
1.6x10^11位
,这是位图的
16x(log N/2)


*假设如果有超过
N/2个
元素,将使用未使用元素的哈希表,否则将使用已使用元素的哈希表。否则,位图的理想情况是当哈希表已满时,这样可以节省超过
log_2(N)

的空间。听起来他说的是打包许多布尔标志,以便每个电话号码索引一个位。但这个问题可能与堆栈溢出无关。当我提到compressed trie时,他让我编写代码,但我不能:(啊,我明白了。如果你要提到一个数据结构,了解它是什么可能是一个明智的想法。虽然了解它并不意味着你知道如何立即编写代码。此外,现在我回顾维基百科的文章,我被提醒说,压缩的trie通常会随着使用或未使用的ele的数量而变得更节省空间因此,在这种情况下,压缩trie不是理想的选择,因为可能没有太多的压缩。这可能是面试官试图通过编码让你看到的。不确定他是否想看到……但我之所以建议压缩trie,是因为大多数时间都是电话号码的代码(前3位数字)保持不变。公平点是,尽管它的工作情况取决于数据。如果预期的数据结构是位图,那么它不太可能被限制在足够小的区域内,从中收集电话号码,以允许使用区号进行大量压缩。“正在使用”措辞让我觉得要么区号可以完全忽略(所有号码都是相同的区号),要么区号的种类太多,区号几乎没有或根本没有好处,因为你需要知道所有使用区号的电话号码,以确定号码是否未被使用。