Где я могу использовать метод из алгоритма большинства голосов

Как видно из ответов на алгоритм большинства линейного времени?, можно вычислить большинство массива элементов в линейное время и log(n) пространство.

показано, что каждый, кто видит этот алгоритм считает, что это классная техника. Но обобщается ли эта идея на новые алгоритмы?

Кажется, скрытая сила этого алгоритма заключается в сохранении счетчика, который играет сложную роль-например, " (количество мажоритарных элементов до сих пор) - (пока подсчет второго большинства)". Существуют ли другие алгоритмы, основанные на той же идее?

3 ответов


Umh, давайте сначала начнем понимать, почему алгоритм работает, чтобы "изолировать" идеи там.

суть алгоритма заключается в том, что если у вас есть мажоритарный элемент, то вы можете сопоставить каждое его вхождение с "другим" элементом, а затем у вас есть еще несколько "запасных".

Итак, у нас есть счетчик, который подсчитывает количество "запасных" экземпляров нашего ответа гостя. Если он достигает 0, то это не мажоритарный элемент для запуска подпоследовательности от того, когда мы "избрали" "текущий" элемент в качестве основного элемента гостя до" текущей " позиции. Кроме того, поскольку наш "гостевой" элемент соответствует каждому другому вхождению элемента в рассматриваемой подпоследовательности, в рассматриваемой подпоследовательности нет основных элементов.

вот так:

  1. наш алгоритм дает правильный ответ, только если есть основной элемент, и
  2. если есть основной элемент, то он все равно будет, если мы проигнорируем " текущий" подпоследовательность, когда счетчик идет к нулю

очевидно видеть противоречие, что если существует основной элемент, то у нас есть суффикс всей последовательности, Когда счетчик никогда не доходит до нуля.

теперь: какая идея может быть использована в новых алгоритмах O(1) размера O (n) времени?

для меня вы можете применить эту технику всякий раз, когда вам нужно вычислить свойство P о последовательности элементов, которые:

  1. может быть exteded от seq[n, m] to seq[n, m+1] в O (1) раз, если Q(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 Мисра и Давид Грис иметь документ под названием Поиск Повторяющихся Элементов (страница ACM), который обобщает его на элемент, повторяющий более n / k раз (K=2 является проблемой большинства).

конечно, это, вероятно, очень похоже на исходную проблему, и вы, вероятно, ищете "разные" алгоритмы.

вот пример, который, возможно, разные.

дайте алгоритм, который обнаружит, если строка скобок ('('и ')') хорошо сформирована.

Я считаю, что стандартное решение-сохранить счетчик.

Примечание:

Что касается ответов, которые не могут быть постоянным пространством и т. д., спросите их о модели вычисления. Например, в модели Word RAM вы предполагаете, что целые числа / индексы массива и т. д. являются O (1).

многие люди неправильно смешивают и сопоставляют модели. Например, они с радостью будут иметь входной массив n целые числа-O(n), имеют индекс массива-O(1), но счетчик они считают Omega (log n) и т. д., Что является нонсенсом. Если они хотят рассмотреть размер в битах, то сам вход является Omega (N log n) и т. д.


для людей, которые хотят понять, что делает этот алгоритм и почему он работает:посмотреть мой подробный ответ!--9-->.

здесь я опишу естественное расширение этого алгоритма (или обобщение). Так что в стандартный алгоритм мажоритарного голосования вы должны найти элемент, который появляется не менее n/2 раз в потоке, где n размер потока. вы можете сделать это O(n) время (с крошечной константой и в O(log(n)) космос, в худшем случае и крайне маловероятный.


обобщенный алгоритм позволяет найти k наиболее частые пункты, где каждый раз появлялись по крайней мере 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