Algorithm 删除内存有限的重复字符串
假设我们有一个字符串列表,不能将整个列表加载到内存中,但可以从文件中加载部分列表。解决这一问题的最佳方法是什么?一种方法是对文件进行排序,然后在排序列表上通过一次迭代删除重复项。这种方法只需要很少的额外空间和Algorithm 删除内存有限的重复字符串,algorithm,data-structures,Algorithm,Data Structures,假设我们有一个字符串列表,不能将整个列表加载到内存中,但可以从文件中加载部分列表。解决这一问题的最佳方法是什么?一种方法是对文件进行排序,然后在排序列表上通过一次迭代删除重复项。这种方法只需要很少的额外空间和O(nlogn)对磁盘的访问 另一种方法基于哈希:使用字符串的哈希代码,并加载包含哈希代码位于特定范围内的所有字符串的子列表。可以保证,如果装载了x,并且有一个副本,则该副本也将装载到同一个存储桶中。 这需要O(n*#bucket)访问磁盘,但可能需要更多内存。如果需要,您可以递归调用该过程
O(nlogn)
对磁盘的访问
另一种方法基于哈希:使用字符串的哈希代码,并加载包含哈希代码位于特定范围内的所有字符串的子列表。可以保证,如果装载了x
,并且有一个副本,则该副本也将装载到同一个存储桶中。
这需要
O(n*#bucket)
访问磁盘,但可能需要更多内存。如果需要,您可以递归调用该过程(使用不同的哈希函数)。我的解决方案是进行合并排序,这样可以使用外部内存。排序之后,搜索重复项将像只比较两个元素一样简单
例如:
0:猫
1:狗
2:鸟
3:猫
4:大象
5:猫
合并排序
0:鸟
1:猫
2:猫
3:猫
4:狗
5:大象
然后简单地比较0&1->无重复项,继续前进。
1&2->duplicate,remove 1(这可能很简单,只需用空字符串填充它,以便稍后跳过)
比较2和3->删除2
等等
删除1&2而不是2&3的原因是它允许更有效的比较——您不必担心跳过已删除的索引。文件有多大?你的记忆力有什么限制?目标机器和语言是什么?什么样的弦?他们要多久?预计有多少个副本?如果允许使用外部工具,GNU/Linux
sort
程序可以对大于内存的文件进行排序,并删除副本。如果文件已经排序,请参阅uniq
程序。@0xbe5077ed:这个广泛问题的一个具体情况是:在外部排序中,您可以在算法的第二次(即合并)过程中删除重复项。@JimMischel:删除pass1中批次中的重复项可以减少批次,保存合并工作。在读取输入时,还可以通过构建一个Trie,甚至是一个DAWG来对更大的pass1批进行排序,以紧凑地表示到目前为止看到的字符串集(在过程中查找重复项)。请看我的答案