在单次传递中在O(n)时间内从大量URL中查找唯一URL

时间:2012-07-01 05:20:59

标签: c++ python algorithm

最近我在接受采访时被问到这个问题。我在O(n)时间给出了答案,但是两次通过。如果网址列表无法适应内存,他还问我如何做同样的事情。非常感谢任何帮助。

5 个答案:

答案 0 :(得分:6)

如果这一切都适合内存,那么问题很简单:创建两组(选择您喜欢的数据结构),两者最初都是空的。一个将包含唯一的URL,另一个将包含多次出现的URL。扫描URL列表一次。对于每个URL,如果它存在于唯一集中,则将其从唯一集中删除并将其放入多个集中;否则,如果多重集中不存在,则将其添加到唯一集合中。

如果该组不适合内存,则问题很难解决。 O(n)的要求并不难以满足,但“单程”(似乎不包括随机访问等)的要求很难;如果没有数据限制,我认为这是不可能的。您可以使用具有集合大小限制的set方法,但是这很容易被数据的不幸排序所击败,并且无论如何只有一定的概率(<100%)找到唯一元素(如果存在)

编辑:

如果您可以设计一个存储在大容量存储中的集合数据结构(因此它可能比存储器中的大,并且可以在O(1)(摊销)时间内进行查找,插入和删除,那么您可以只需使用第一种方法来解决第二个问题。也许所有采访者都在寻找的是将URL转储到具有URL和计数列的UNIQUE索引的数据库中。

答案 1 :(得分:2)

可以尝试使用Trie结构来保存数据。它被压缩,因此它需要更少的内存,因为常见网址部分的内存重用。

循环看起来像:

add string s to trie;
check that added string is not finished in existing node
    internal node -> compress path
    leaf node -> delete path

答案 2 :(得分:0)

对于“适合内存”的情况,您可以使用以下两个哈希表(伪代码):

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();

答案 3 :(得分:0)

基于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)')

获取数据,然后执行“从任意组中选择*,其中count(*)= 1)”

答案 4 :(得分:-1)

这实际上是一个经典的面试问题,他们期待的答案是你首先对网址进行排序,然后进行二元搜索。 如果它不适合内存,你可以用文件做同样的事情。