Это стандартная проблема в алгоритмах потокового (где у вас есть огромный (потенциально бесконечный) поток данных) и вам нужно вычислить некоторую статистику из этого потока, пройдя через этот поток один раз.
Ясно, что вы можете подойти к нему с помощью хэширования или сортировки, но с потенциально бесконечным потоком вы явно исчерпали память. Поэтому вам нужно сделать что-то умное здесь.
Большинство элементом является элемент, который встречается более половины размера массива. Это означает, что элемент большинства встречается больше, чем все остальные элементы, объединенные, или если вы подсчитываете количество раз, появляется элемент большинства и вычитаете число всех остальных элементов, вы получите положительное число.
Итак, если вы подсчитаете количество некоторых элементов и вычтите количество всех остальных элементов и получите число 0 - тогда ваш исходный элемент не может быть элементом большинства. Это, если основание для правильного алгоритма:
Имейте две переменные, счетчик и возможный элемент. Итерируйте поток, если счетчик равен 0 - вы перезаписываете возможный элемент и инициализируете счетчик, если номер совпадает с возможным элементом - увеличивайте счетчик, в противном случае уменьшите его. код Python:
def majority_element(arr):
counter, possible_element = 0, None
for i in arr:
if counter == 0:
possible_element, counter = i, 1
elif i == possible_element:
counter += 1
else:
counter -= 1
return possible_element
Это ясно видно, что алгоритм O(n)
с очень малой константой, прежде чем O(n)
(например, 3). Также похоже, что сложность пространства составляет O(1)
, потому что у нас есть только три инициализированных переменных. Проблема в том, что одна из этих переменных является счетчиком, который потенциально может вырасти до n
(когда массив состоит из одинаковых номеров). И для хранения номера n
вам необходимо O(log (n))
. Так с теоретической точки зрения это O(n)
время и O(log(n))
пространство. С практического вы можете поместить номер 2^128 в longint, и это количество элементов в массиве невообразимо велико.
Также обратите внимание, что алгоритм работает только в том случае, если имеется элемент большинства. Если такой элемент не существует, он все равно вернет некоторое число, которое, безусловно, будет неправильным.(легко изменить алгоритм, чтобы определить, существует ли мажоритарный элемент)
Канал истории: этот алгоритм был изобретен где-то в 1982 году Бойером Муром и назван Boyer–Moore majority vote algorithm.
Если кто-то ищет правильный подход к этой классической проблеме в теории потоковых алгоритмов, взгляните на [мой подробный ответ] (http://stackoverflow.com/a/36243686/1090562) – 2016-03-27 04:03:09