繁体   English   中英

我在哪里可以使用多数投票算法中的技术

[英]Where can I use a technique from Majority Vote algorithm

线性时间多数算法的答案中可以看出? ,可以在线性时间和log(n)空间中计算大部分元素数组。

结果表明,看到该算法的每个人都认为这是一项很酷的技术。 但是这个想法能推广到新算法吗?

似乎该算法的隐藏功能在于保持一个扮演复杂角色的计数器 - 例如“(到目前为止的多数元素计数) - (迄今为止的第二多数计数)”。 是否有其他基于相同思想的算法?

嗯,让我们首先开始了解算法为什么有效,以便“隔离”那里的想法。

该算法的要点是,如果你有一个多数元素,那么你可以将它的每次出现都与一个“另一个”元素相匹配,然后你就有更多的“备用”元素。

所以,我们只有一个计数器来计算我们的客人回答的“备用”出现次数。 如果它达到 0,那么它不是从我们“选择”“当前”元素作为“当前”position 的来宾主要元素开始的子序列的多数元素。 此外,由于我们的“guest”元素与所考虑的子序列中的所有其他元素匹配,因此所考虑的子序列中没有主要元素。

现在,因为:

  1. 我们的算法只有在存在主要元素时才会给出正确答案,并且
  2. 如果有一个主要元素,那么当计数器变为零时,如果我们忽略“当前”子序列,它仍然是

很明显,通过矛盾可以看出,如果存在一个主要元素,那么当计数器永远不会为零时,我们就有整个序列的后缀。

现在:在新的 O(1) 大小 O(n) 时间算法中可以利用的想法是什么?

对我来说,只要你必须在一系列元素上计算属性P ,你就可以应用这种技术:

  1. 如果Q(seq[n, m+1])不成立,可以在 O(1) 时间内从seq[n, m]扩展到seq[n, m+1]
  2. P(seq[n, m])可以在 O(1) 时间和空间内从P(seq[n, j])P(seq[j, m])计算,如果Q(seq[n, j])持有

在我们的例子中, P是我们“选定”主要元素的“备用”出现, Q是“ P为零”。

如果您以这种方式看待事物, 最长公共子序列会利用相同的想法(不知道它的“酷因子”;))

Jaydev Misra 和 David Gries 有一篇名为Find Repeated Elements ( ACM page ) 的论文,将其概括为重复超过 n/k 次的元素(k=2 是多数问题)。

当然,这可能与原始问题非常相似,您可能正在寻找“不同”的算法。

这是一个可能不同的示例。

给出一个算法,该算法将检测一串括号('('和')')是否格式正确。

我相信标准的解决方案是维护一个计数器。

边注:

至于声称不能是恒定空间等的答案,请向他们询问计算的 model。 例如,在 WORD RAM model 中,您假设整数/数组索引等为 O(1)。

很多人错误地混合和匹配模型。 例如,他们很乐意让 n 个整数的输入数组为 O(n),数组索引为 O(1) 空间,但他们认为计数器为 Omega(log n) 等,这是无稽之谈。 如果他们想以位为单位考虑大小,那么输入本身就是 Omega(n log n) 等。

对于想了解该算法的作用以及为什么起作用的人:请查看我的详细答案

在这里,我将描述该算法的自然扩展(或泛化)。 因此,在标准多数投票算法中,您必须找到在 stream 中至少出现n/2次的元素,其中n是 stream 的大小。 您可以在O(n)时间内完成此操作(使用一个很小的常数和O(log(n))空间,更糟糕的情况且极不可能。


广义算法允许您找到k个最频繁的项目,其中每次在原始 stream 中出现至少n/(k+1)次。 请注意,如果 k=1,您最终会遇到原始问题。

这个问题的解决方案与原来的解决方案非常相似,除了不是一个计数器和一个可能的元素,您维护 k 个计数器和 k 个可能的元素。 现在逻辑以类似的方式进行。 您遍历数组,如果元素在可能的元素中,则增加它的计数器,如果其中一个计数器为零 - 用新元素替换此计数器的元素。 否则只需减少值。

与原始多数投票算法一样,您需要保证您拥有这 k 个多数元素,否则您必须再次遍历数组以验证您之前找到的可能元素是否正确。 这是我的 python 尝试(尚未进行彻底测试)。

from collections import defaultdict
def majority_element_general(arr, k=1):
    counter, i = defaultdict(int), 0
    while len(counter) < k and i < len(arr):
        counter[arr[i]] += 1
        i += 1

    for i in arr[i:]:
        if i in counter:
            counter[i] += 1
        elif len(counter) < k:
            counter[i] = 1
        else:
            fields_to_remove = []
            for el in counter:
                if counter[el] > 1:
                    counter[el] -= 1
                else:
                    fields_to_remove.append(el)
            for el in fields_to_remove:
                del counter[el]

    potential_elements = counter.keys()
    # might want to check that they are really frequent.
    return potential_elements

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM