【问题标题】:Determining if an array has a k-majority element确定数组是否具有 k 多数元素
【发布时间】:2012-08-20 10:53:47
【问题描述】:

假设,给定一个 n 元素多重集 A(未排序),我们 需要一个 O(n) 时间算法来确定 A 是否包含多数元素,即 在 A 中出现超过 n/2 次的元素。很容易在 O(n) 时间内通过以下方式解决此问题 使用线性时间选择算法找到中位数(称为 x),然后计数 x 在 A 中出现多少次,如果计数超过 n/2,则将其作为多数返回 (否则答案是“没有多数”)。现在考虑以下概括 问题的根源:给定 A 和一个整数 k

现在我想出了两个解决方案,但都不能完全满足 O(n log k) 要求。我立即看到我可以使用 O(n log n) 算法对数组进行排序,然后查看是否有任何元素线性重复超过 n/k 次,但这是 O(n log n) 而不是 O(n log k)

我还发现并在一定程度上理解了一种 O(nk) 方法,方法是创建一个与输入数据类型相同的数组和一个 k 长的 int。然后将每个元素放入一个空元素中,增加它的计数器,或者如果它匹配其中的一个元素,增加它的计数器,直到我们到达第 k+1 个唯一元素,此时你将所有计数器减 1,直到一个达到 0,此时它是被认为是空的,可以将新元素放入其中。依此类推,直到输入数组的末尾。然后检查我们完成后剩下的所有元素,看看它们是否出现超过 n/k 次。但由于这涉及检查 n 个原始元素与所有 k 个新数组元素,它是 O(nk)。关于如何在 O(n log k) 中解决这个问题的任何提示?我认为 O(nk) 算法符合他希望我们思考的方式,但我不确定从这里去哪里。

【问题讨论】:

  • 感谢 avi cohen,您的想法帮助我走上了正确的道路,但在将其划分为小节而不进行 nk 比较后,在弄清楚如何进行操作时遇到了一些问题,但最终还是解决了

标签: algorithm


【解决方案1】:

您描述的方法只需要递归使用。

记住select将小于或等于中位数的元素移动到中位数的左侧。

如果A 的大小为n

A 的中位数。 现在找到由中位数划分的两个长度为n/2 的子多组中的每一个的中位数。 找到由中位数划分的四个长度为n/4 的子多组中的每一个的中位数。 继续递归直到叶子的长度为n/k。 现在递归树的高度是O(lgk)。 在递归树的每一层,都有O(n) 操作。 如果存在至少重复 n/k 次的值,那么它将位于其中之一 这些k 的长度为n/k 子多组。 最后的操作也在O(n) 中完成。 这样你就得到了O(nlgk)的请求运行时间。

【讨论】:

    【解决方案2】:

    O(kn) 算法

    我想知道 O(kn) 算法是否可能更符合以下原则:

    1. 查找 k 个规则间隔的元素(使用与中位数类似的线性选择算法)
    2. 数一数你为这些中的每一个获得了多少匹配项

    我们的想法是,如果一个元素出现 n/k 次,它一定是其中之一。

    O(nlogk) 算法

    也许您可以将问题中提出的方案与树结构一起使用来保存 k 个元素。那么这意味着对于一个整体的 O(nlogk) 而言,搜索匹配只会是 log(k) 而不是 k?

    请注意,您应该将树用于第一遍(您将在其中找到我们需要考虑的 k 个候选者)和第二遍计算每个元素的确切计数。

    另请注意,您可能希望使用惰性评估方案来递减计数器(即标记需要递减的整个子树,并仅在下次使用该路径时传播递减量)。

    O(n) 算法

    如果您在现实生活中遇到这种情况,我会考虑使用基于哈希的字典来存储直方图,因为这应该是一个快速的解决方案。

    例如在 Python 中,您可以使用(平均)O(n) 时间解决这个问题

    from collections import Counter
    A=[4,2,7,4,6]
    k=3
    
    element,count = Counter(A).most_common()[0]
    
    if count>=len(A)//k:
        print element
    else:
        print "there is no majority"
    

    【讨论】:

      【解决方案3】:

      我不知道你是否看过这个,但它可能有助于给你一些想法:

      假设您知道数组 L 中有多数元素。

      找到元素的一种方法如下:

      Def FindMajorityElement(L):
      
          Count = 0
      
          Foreach X in L
      
              If Count == 0
                  Y = X
      
              If X == Y
                  Count = Count + 1
              Else
                  Count = Count - 1
      
          Return Y
      

      O(n) 时间,O(1) 空间

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-21
        • 1970-01-01
        • 2014-01-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多