在多个链表中查找重复项的算法

时间:2011-05-09 21:51:35

标签: algorithm optimization linked-list

在多个(大型)链接列表中查找重复项的最快方法是什么。 我将尝试用数组来说明问题,只是为了让它更具可读性。 (我使用0-9中的数字来表示简单而不是指针)。

list1[] = {1,2,3,4,5,6,7,8,9,0};
list2[] = {0,2,3,4,5,6,7,8,9,1};
list3[] = {4,5,6,7,8,9,0,1,2,3};
list4[] = {8,2,5};
list5[] = {1,1,2,2,3,3,4,4,5,5};

如果我现在问:'列表1-5中是否存在数字8?'我可以对列表进行排序,删除重复项,对所有列表重复此操作并将它们合并到“超级列表”中,并查看(新)重复项的数量是否等于我搜索的列表数量。假设我得到了正确的重复数,我可以假设我搜索的内容(8)存在于所有列表中。 如果我改为搜索1,我将只得到四个重复项 - 并未在所有列表中找到。

在没有以任何方式排序和/或更改列表的情况下,是否有更快/更智能/更好的方法来实现上述目标?

P.S。:这个问题主要是出于纯粹的好奇心而没有别的! :)

3 个答案:

答案 0 :(得分:6)

只需将每个数字放入哈希表中,并将该项目的出现次数存储在表格中。当你找到另一个时,只需增加计数器。 O(n)算法(所有列表中的n个项目)。

如果要存储每个列表中的列表,则还需要在每个项目下存储一组表示。你可以使用任何集合表示 - 位向量,列表,数组等。这将告诉你该项目所属的列表。这不会从O(n)改变它,只是按常数因子增加工作量。

答案 1 :(得分:1)

问题有点模糊,所以答案取决于你想要的东西。

哈希表是询问有关重复项的一般问题的正确答案,因为它允许您只浏览每个列表一次以构建一个能够回答大多数问题的表;但是,有些问题不需要一个。

似乎可以回答您问题的可能案例:

您只需要知道每个列表中是否存在某个值? - 检查第一个列表,直到找到该值。如果没有,你就完成了:事实并非如此。重复每个连续列表。如果搜索了所有列表并找到了值,则会在每个列表中重复该列表。在这个算法中,没有必要查看每个列表中的每个值,甚至每个列表,所以这将是最快的。

您是否需要知道是否存在任何重复项? - 如果按数字键入的哈希表中的任何值的计数大于0,则表示重复...如果这是您需要知道的全部内容,则可以在此处退出。

您需要重复的数量吗?     在每个表中,分开? - 将每个值乘以列表数,并添加正在处理的列表的编号。将其存储为哈希键并计算重复项。处理完所有列表后,您将拥有一个可以回答各种问题的表格。要检查特定值的重复项,请将其乘以列表计数并检查顺序哈希键。如果每个列表都有一个,则每个列表中都会显示该编号。如果在该范围内所有计数都大于1,则每个列表中的数字都会重复。

答案 2 :(得分:1)

定义数组hash并将所有位置值设置为0

define hash[MAX_SYMBOLS] = {0};
define new_list[LENGTH]
defile list[LENGTH] and populate

现在,对于list中的每个元素,请将此数字用作hash中的索引,并增加hash的位置。该数字的每次存在都会使该hash位置的值增加一次。因此,重复值i将具有hash[i] > 1

for i=0 to (n - 1)
  do
    increment hash[list[i]]
endfor

如果要删除重复项并创建新列表,请扫描hash数组以及每个i的存在,即。如果hash[i] > 0按照它们出现在原始列表中的顺序将它们加载到新列表中。

define j = 0
for i=0 to (n - 1)
  do
    if hash[list[i]] is not 0
      then
        new_list[j] := i
        increment j
    endif
endfor

请注意,使用负数时,您将无法直接使用这些值进行索引。要使用负数,首先我们可以找到负数的最大幅度,并在我们使用它们来索引hash数组时使用该幅度来添加到所有数字。

find the highest magnitude of negative value into min_neg

for i=0 to (n - 1)
  do
    increment hash[list[i + min_neg]]
endfor

或者在实现中,您可以分配连续的内存,然后在分配的内存块的中间定义一个指针,这样您就可以在前后方向上移动,这样就可以使用负索引。您需要确保在指针的正面和背面有足够的内存使用。

int *hash = malloc (sizeof (int) * SYMBOLS)
int *hash_ptr = hash + (int)(SYMBOLS/2)

现在,您可以使用hash_ptr[-6]

执行hash_ptr[i]或某些-SYMBOLS/2 < i < SUMBOLS/2 + 1