如何从链表中删除重复的奇数?

时间:2011-02-12 06:49:43

标签: c data-structures linked-list

要求/约束​​:

  1. 仅删除重复项
  2. 保留一份副本
  3. 列表最初未排序
  4. 如何在C中实现? (非常感谢算法和/或代码!)

6 个答案:

答案 0 :(得分:2)

如果列表很长并且你想要合理的性能并且你可以分配额外的log(n)内存,你可以使用qsort或合并排序在nlog(n)中排序:

http://swiss-knife.blogspot.com/2010/11/sorting.html

然后你可以删除n中的重复项(总数为:nlog(n)+ n)

如果你的名单非常小,你可以像jswolf19那样建议,你会得到:n(n-1)/ 2最差。

答案 1 :(得分:2)

我要么

  • 合并列表,然后进行线性扫描以删除重复项
  • 使用基于插入排序的算法,该算法在重新构建列表时已经删除了重复项

前者会更快,后者更容易从头开始实现:只需通过弹出旧列表中的元素并通过扫描它们将它们插入到新列表中来构建一个新列表,直到找到更大值的元素(在这种情况下,您将元素插入列表)或相等的值(在这种情况下,您丢弃元素)。

答案 2 :(得分:2)

检测/删除重复项有几种不同的方法:

嵌套循环

按顺序取下一个值,然后扫描到列表末尾以查看是否再次出现此值。这是O(n 2 ) - 虽然我认为界限可以说较低? - 但实际效果可能会更好,因为只能完成从iend(不是0end)的扫描,并且可能会提前终止。除了少数变量外,这不需要额外的数据。

(请参阅Christoph的答案,如何使用链接列表的遍历和破坏性“附加”到新列表来完成此操作 - 例如,嵌套循环不必像嵌套循环一样“感觉”。)< / p>

排序和过滤

对列表进行排序(可以修改mergesort以在链表上工作),然后检测重复值(它们将是并排的)。排序很好,这是O(n * lg(n))。排序阶段通常是/可能是破坏性的(例如你有“一个副本”)但它已被修改; - )

扫描并保持查找

扫描列表并在扫描列表时将值添加到查找中。如果查找已经包含所述值,那么就有重复!如果查找访问是O(1),则该方法可以是O(n)。通常,“散列/字典”或“集合”用作查找,但是如果仅使用有限范围的积分,则数组将正常工作(例如,索引是值)。这需要额外的存储空间,但没有“额外的副本” - 至少在文字阅读中是这样。

对于n的小值,big-O几乎毫无价值; - )

快乐的编码。

答案 3 :(得分:1)

那么,您可以先对列表进行排序,然后检查重复项,或者您可以执行以下操作之一:

for i from 0 to list.length-1
    for j from i+1 to list.length-1
        if list[i] == list[j]
            //delete one of them
        fi
    loop
loop

答案 4 :(得分:1)

这可能是最无法优化的废话,但它可能会奏效。

遍历列表,每次进入下一个对象时都按住指向上一个对象的指针。在迭代循环内部迭代遍历它以检查重复。如果存在重复,现在回到主迭代循环中,获取下一个对象。将前面的对象指针设置为刚刚检索到的对象的下一个对象,然后跳出循环并重新启动整个过程,直到没有重复。

答案 5 :(得分:0)

您可以使用哈希表在线性时间内完成此操作。

您希望按顺序扫描列表。每次遇到奇数编号的元素时,请在哈希表中查找。如果该数字已经在哈希表中,则将其从列表中删除,如果没有将其添加到哈希表中并继续。

基本上这个想法是,对于您在列表中扫描的每个元素,您可以在恒定时间内检查它是否与您看到的前一个元素重复。这只需要一次通过你的列表,并且最坏的情况是线性内存量(最坏的情况是列表中的每个元素都是唯一的奇数,因此你的哈希表与你的列表一样长。)