最近在一次采访中被问到这个问题。我在 O(n) 时间内给出了答案,但分两次。他还问我如果 url 列表无法放入内存中该怎么做。很感谢任何形式的帮助。
5 回答
如果这一切都适合内存,那么问题很简单:创建两个集合(选择您喜欢的数据结构),最初都是空的。一个将包含唯一的 URL,另一个将包含多次出现的 URL。扫描一次 URL 列表。对于每一个URL,如果存在于唯一集中,则将其从唯一集中移出,放入多重集中;否则,如果它不存在于多重集中,则将其添加到唯一集中。
如果该集合不适合内存,则问题很困难。O(n) 的要求并不难满足,但“单次通过”的要求(似乎排除了随机访问等)是困难的;我认为如果没有对数据的一些限制,这是不可能的。您可以使用对集合有大小限制的集合方法,但这很容易被不幸的数据排序所破坏,并且无论如何只有一定的概率(<100%)找到一个唯一元素(如果存在)。
编辑:
如果您可以设计一个存在于大容量存储中的集合数据结构(因此它可以大于内存中的容量)并且可以在 O(1)(摊销)时间内进行查找、插入和删除,那么您可以使用它用第一种方法解决第二个问题的结构。也许面试官所寻找的只是将 URL 转储到具有 URL 唯一索引和计数列的数据库中。
可以尝试使用 Trie 结构来保存数据。它被压缩了,所以它会占用更少的内存,作为常见 url 部分的内存重用。
循环看起来像:
add string s to trie;
check that added string is not finished in existing node
internal node -> compress path
leaf node -> delete path
对于“适合内存”的情况,您可以使用如下两个哈希表(伪代码):
hash-table uniqueTable = <initialization>;
hash-table nonUniqueTable = <initialization>;
for-each url in url-list {
if (nonUniqueTable.contains(url)) {
continue;
}
else if (uniqueTable.contains(url)) {
nonUniqueTable.add(url);
uniqueTable.remove(url);
}
else {
uniqueTable.add(url)
}
}
if (uniqueTable.size() > 1)
return uniqueTable.first();
基于 Python
你有一个list
- 不确定它“来自”哪里,但如果你已经在内存中拥有它,那么:
L.sort()
from itertools import groupby
for key, vals in groupby(L, lambda L: L):
if len(vals) == 1:
print key
否则使用存储(可能使用):
import sqlite3
db = sqlite3.connect('somefile')
db.execute('create table whatever(key)')
将您的数据放入其中,然后执行“select * from any group by key where count(*) = 1)”
这实际上是一个经典的面试问题,他们期望的答案是您首先对 url 进行排序,然后进行二分搜索。如果它不适合内存,您可以对文件执行相同的操作。