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

要求/约束​​:

  1. 仅删除重复项
  2. 保留一份副本
  3. 列表最初未排序

如何在C中实现? (非常感谢算法和/或代码!)

如果列表很长并且您想要合理的性能并且您可以分配额外的内存log(n),则可以使用qsort或merge sort对nlog(n)进行排序:

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

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

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

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

嵌套循环

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

(参见Christoph的答案,如何使用链表的遍历和破坏性的“附加”到新列表中来实现这一点 – 例如,嵌套循环不必像嵌套循环那样“感觉”。)

排序和过滤

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

扫描并保持查找

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

对于小的n值,big-O几乎一文不值;-)

快乐的编码。

我也是

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

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

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

 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 

这可能是最不优化的垃圾,但它可能会起作用。

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

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

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

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