【问题标题】:Equivalence testing of n objectsn个对象的等价测试
【发布时间】:2014-11-27 06:24:28
【问题描述】:

假设我们有“n”个对象和一个子例程,它接受两个输入并判断它们是否相等(例如,如果它们相等,它可以将输出作为 1)。

我需要想出一个算法来调用上述函数 O(n log n) 次,并确定输入是否有超过“n/2”个彼此等价的项目。

【问题讨论】:

  • O(n log n) 通常暗示以某种方式进行排序。子程序真的只适用于等于还是比较两者,所以你可以用它来排序?
  • 有一个解决方案需要 O(n) 比较。

标签: algorithm recursion divide-and-conquer


【解决方案1】:

考虑到序列是有序的,你可以使用binary search,它需要O(log n),因为你必须对每个元素都这样做,而且你有n元素,它需要O(n*log n)

【讨论】:

  • 比较器似乎没有提供订购信息。
  • "接受两个输入并判断它们是否相等的子程序"
  • 这通常都无关紧要,我已经阅读了几本关于算法和复杂性分析的书,即使我们的复杂性是 O(nlog n + n) 我们仍然有 ~O(nlog n ) 因为 n 比 nlog n 小,所以你可以把这个词去掉
  • 您无法从该子例程中获得所需的信息。复杂性与它无关。
  • 哦,好吧,我正式失去你了,不知道你在说什么。
【解决方案2】:

您可以使用 Boyer-Moore 多数投票算法,该算法最多进行 n-1 次比较。

function find_majority(A)
    majority = None
    count = 0
    for a in A:
        if count == 0
            majority = a
        else if a == majority
            count += 1
        else
            count -= 1
    return majority

如果在数组中出现超过 n/2 次,则返回最常见的元素。

如果您需要知道是否存在 多数项,那么您可以对数组进行第二次遍历,计算从 find_majority 函数返回的值出现的次数。这又增加了 n 个比较。

【讨论】:

    【解决方案3】:

    这是一个经典的分而治之的解决方案,它给出了 O(n log n)

    分成两个子集,A1 和 A2,...,显示 T(n) 为 O(n log n)。 如果 A 具有多数元素 v,则 v 也必须是 A1 或 A2 或两者的多数元素。这 等价的反积极重述是立即的:(如果 v 在每个中

    http://anh.cs.luc.edu/363/handouts/MajorityProblem.pdf

    【讨论】:

      【解决方案4】:

      Paul Hankin 的回答是 $\mathcal{O}(n)$ 解决方案,非常花哨。

      如果不使用 Boyer-Moore,我们也可以在$\mathcal{O}(nlogn)$ 解决这个问题。每次比较后,我们“丢弃”不同的牌组并将相等的牌组“合并”为一组,以此类推,每次我们丢弃相同数量的牌时,最后剩下的牌或牌组就是“多数” ",然后我们可以再次运行比较来检查卡是否为真。

      由于我们每次丢牌,至少丢一张多数牌和另一张,所以不会影响结果,丢牌的过程是一个“抵消”操作。不管是掉落还是合并,帮助我们减少至少一半的卡。所以递归次数为$logn$,总时间为$nlogn$

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-10
        • 2017-03-29
        • 2011-12-15
        • 2013-12-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多