【问题标题】:Find all elements that appear more than n/4 times in linear time查找在线性时间内出现超过 n/4 次的所有元素
【发布时间】:2014-09-01 16:25:53
【问题描述】:

这个问题是 Skiena 的 4-11。找到多数元素的解决方案 - 重复超过一半是多数算法。我们可以用它找出所有重复 n/4 次的数字吗?

【问题讨论】:

标签: arrays algorithm search


【解决方案1】:

由于您没有提到空间复杂度,一种可能的解决方案是使用 hashtable 映射到计数的元素,然后如果找到该元素,您可以增加计数。

【讨论】:

    【解决方案2】:

    请参阅this paper,了解使用常量内存并以线性时间运行的解决方案,该解决方案将为出现超过 n/4 次的元素找到 3 个候选者。请注意,如果您假设您的数据是作为只能通过一次的流给出的,那么这是您能做的最好的 - 您必须再通过一次流来测试 3 个候选人中的每一个,看看是否它在流中出现超过 n/4 次。但是,如果您先验地假设有 3 个元素出现超过 n/4 次,那么您只需要通过流一次,这样您就可以得到一个线性时间在线算法(只通过流一次),它只需要常数存储。

    【讨论】:

      【解决方案3】:

      通过摩尔投票算法找到出现n/2 times的多数元素

      请参阅摩尔投票算法 (http://www.geeksforgeeks.org/majority-element/) 给定链接的方法 3。

      时间:O(n)

      现在找到多数元素后,再次扫描数组并remove the majority element 或使其成为-1.

      时间:O(n)

      现在对数组的剩余元素应用摩尔投票算法(但现在忽略 -1,因为它之前已经包含在内)。新的多数元素出现n/4 times.

      时间:O(n)

      总时间:O(n)

      额外空间:O(1)

      您可以对出现超过 n/8,n/16,.... 次的元素执行此操作

      编辑:

      可能存在数组中没有多数元素的情况:

      例如如果输入数组是{3, 1, 2, 2, 1, 2, 3, 3},那么输出应该是[2, 3]

      给定一个大小为 n 的数组和一个数字 k,找出所有出现次数超过 n/k 次的元素

      请参阅此链接以获取答案: https://stackoverflow.com/a/24642388/3714537

      参考资料:

      http://www.cs.utexas.edu/~moore/best-ideas/mjrty/

      【讨论】:

      • 如果最常见的元素不是大多数怎么办?例如,如果 1、2 和 3 各出现 n/3 次。
      • 上面链接的方法3在找到潜在的多数元素后检查多数元素是否存在。
      • 但如果没有多数元素,该方法几乎可以给你任何东西。
      • 那篇论文末尾的注释提到了比您建议的要好得多的较晚版本(实际上是早于 发布 年,出于愚蠢的原因)。见cs.utexas.edu/users/misra/scannedPdf.dir/…
      【解决方案4】:

      Misra and Gries 描述了几种方法。我不完全理解他们的论文,但一个关键的想法是使用袋子

      Boyer and Moore's original majority algorithm paper 有很多关于 FORTRAN 代码形式验证的难以理解的证明和讨论,但它对多数算法的工作原理有一个很好的解释开始。关键概念始于这样一个想法,即如果大多数元素是 A 并且您一次删除一个 A 的副本和其他内容的副本,那么最终您将只有A。接下来,应该清楚的是,删除两个不同的项目,两者都不是A,只能增加A 持有的多数。因此,删除 任何 对项目是安全的,只要它们不同。然后可以将这个想法具体化。从列表中取出第一项并将其粘贴在一个盒子中。取出下一个物品并将其粘在盒子里。如果他们是一样的,让他们都坐在那里。如果新的不同,请将其与盒子中的物品一起扔掉。重复直到所有物品都在盒子里或垃圾桶里。由于盒子一次只允许有一种物品,因此可以非常有效地表示为一对(item type, count)

      找到所有可能出现超过n/k 次的项目的概括很简单,但解释它的工作原理有点困难。基本思想是我们可以找到并销毁k distinct 元素组,而无需更改任何内容。为什么?如果w > n/kw-1 > (n-k)/k。也就是说,如果我们去掉一个流行元素,同时也去掉k-1other元素,那么流行元素仍然流行!

      实现:不只允许 一个 类型的项目在框中,而是允许 k-1 个项目。每当您看到一组 k 不同 项目出现时(也就是说,框中有 k-1 类型,而到达的类型与它们中的任何一个都不匹配),你扔一个垃圾箱中的每种类型,包括刚刚到达的那种。我们应该为这个“盒子”使用什么数据结构?好吧,当然是一个包!正如 Misra 和 Gries 所解释的,如果可以对元素进行排序,那么具有 O(log k) 基本操作的基于树的包将使整个算法的复杂度为 O(n log k)。需要注意的一点是,删除每个元素之一的操作很昂贵(我认为 O(k log k)),但该成本在这些元素的到达时分摊,所以没什么大不了的。当然,如果您的元素是可散列的而不是可排序的,则可以改用基于散列的包,在某些常见假设下,它会提供更好的渐近性能(但不能保证)。如果您的元素是从一个小的有限集合中提取的,您可以保证这一点。如果它们只能比较平等,那么你的包会变得更贵,我很确定你最终会得到像 O(nk) 这样的东西。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-18
        相关资源
        最近更新 更多