【问题标题】:How will you delete duplicate odd numbers from a linked list?你将如何从链表中删除重复的奇数?
【发布时间】:2011-02-12 06:49:42
【问题描述】:

要求/约束​​:

  1. 只删除重复项
  2. 保留一份
  3. 列表最初没有排序

这如何在 C 中实现? (算法和/或代码将不胜感激!)

【问题讨论】:

    标签: c data-structures linked-list


    【解决方案1】:

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

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

    那么就可以去除n中的重复项(总数为:nlog(n) + n)

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

    【讨论】:

    【解决方案2】:

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

    嵌套循环

    依次取下一个值,然后扫描到列表末尾,看看这个值是否再次出现。这是 O(n2) - 尽管我相信界限可以更低? -- 但实际性能可能会更好,因为只完成了从iend(不是0end)的扫描,并且它可能会提前终止。除了一些变量之外,这不需要额外的数据。

    (请参阅 Christoph 的回答,了解如何仅使用链表的遍历和破坏性的“附加”到新列表来完成 - 例如,嵌套循环不必“感觉”像嵌套循环。)

    排序和过滤

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

    扫描并保持查找

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

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

    编码愉快。

    【讨论】:

    • @Christoph 确实(并已更正)!我被我新发现的上标和下标的使用迷住了:-)
    【解决方案3】:

    我愿意

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

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

    【讨论】:

    • +1 指出 排序本身 可以删除重复项(例如,对于链表上的合并排序也是如此)。一个“缺点”是无法维持原来的顺序。
    • 如果可以的话,我会再次 +1 :-) 如上所述,使用修改后的“插入排序”可以在没有实际排序的情况下完成——只需遍历旧列表并仅添加 如果没有找到“新”列表的末尾(对适合链表的嵌套循环的修改)。好处是保持原始顺序——如果重要的话。
    • @pst:我想过这样做,但这意味着您将始终必须扫描整个“新”列表,而使用排序,您可以在更大的时候立即停止到达元素...
    【解决方案4】:

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

    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
    

    【讨论】:

      【解决方案5】:

      这可能是最未经优化的废话,但它可能会起作用。

      遍历列表,每次进入下一个对象时都持有指向前一个对象的指针。在您的迭代循环中遍历所有内容以检查重复项。如果有重复,现在回到主迭代循环,获取下一个对象。将前一个对象的指针设置为刚刚检索到的对象的下一个对象,然后跳出循环并重新开始整个过程​​,直到没有重复。

      【讨论】:

        【解决方案6】:

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

        您希望按顺序浏览列表。每次遇到奇数元素时,请在哈希表中查找它。如果该数字已经在哈希表中,则将其从列表中删除,否则将其添加到哈希表中并继续。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2022-12-17
          • 2017-02-02
          • 2013-12-14
          • 1970-01-01
          • 2022-11-14
          • 2020-06-09
          • 2018-11-08
          相关资源
          最近更新 更多