Мажорирующий элемент — различия между версиями
Никита (обсуждение | вклад) (→Формулировка задачи) |
Никита (обсуждение | вклад) (→Источники) |
||
| Строка 62: | Строка 62: | ||
== Источники == | == Источники == | ||
| − | * [http:// | + | * [http://habrahabr.ru/post/167177/ Habrahabr - Поиск часто встречающихся элементов в массиве] |
* [http://algolist.ncstu.ru/olimp/poi_sol.php#a15 Algolist - Решение задачи 15] | * [http://algolist.ncstu.ru/olimp/poi_sol.php#a15 Algolist - Решение задачи 15] | ||
[[Категория: Амортизационный анализ]] | [[Категория: Амортизационный анализ]] | ||
Версия 18:47, 24 мая 2013
Содержание
Формулировка задачи
Требуется в массиве длиной найти элемент, встречающийся более раз. Гарантируется, что такой элемент существует.
Решение за O(N)
Алгоритм можно представить следующим образом: пусть на вечеринке собрались людей, и каждому из них соответствует один элемент из массива. Когда встречаются двое с разными элементами, то они образуют пару и садятся. В конце концов останутся стоять только гости с одинаковыми элементами. Это и есть искомый элемент.
Псевдокод
findMajorityElement(a, N)
count = 0 // количество людей, оставшихся стоять
candidate = null
for i = 0 to N - 1
if count == 0 // никто не стоит
candidate = a[i] // встанет текущий элемент
count++ // увеличим количество стоящих
else // кто-то стоит
if a[i] == candidate // стоит такой же элемент
count++ // увеличим количество стоящих
else // стоит другой элемент => подобрали пару
count-- // уменьшим количество стоящих
return candidate
Доказательство
На i-ом шаге выполняется следующий инвариант: если , то - мажорирующий элемент на подмассиве , либо мажорирующего элемента на данном подмассиве не существует. Тогда на N-ом шаге будет содержать мажорирующий элемент на всем массиве, т.к. гарантируется его существование. Покажем, что данный инвариант всегда выполняется.
Пусть данный инвариант выполняется на k-ом шаге. Тогда на (k+1)-ом шаге возможны 3 варианта:
-
Очевидно, что на подмассиве мажорирующего элемента не существует, так как все элементы разбились на пары. Тогда только может быть мажорирующим элементом.
- и
Если на подмассиве существует мажорирующий элемент, то он находится в . Тогда, в силу равенства и , если на подмассиве существует мажорирующий элемент, то он тоже будет равен .
- и
Если на подмассиве существует мажорирующий элемент, то он находится в . Тогда, в силу неравенства и , образовалась новая пара. Если не станет равным нулю, то опять же мажорирующим элементом может быть только candidate, так как для всех остальных мы нашли пару, а значит встречаются они не более раз.
Всего происходит итераций, каждая из которых обрабатывается за . Итоговая асимптотика .
Обобщение на случай поиска элемента, встречающегося N/K раз
"Хитрое" решение
Выберем случайный элемент в массиве и проверим, встречается ли он больше, чем раз. Будем делать так, пока не найдем подходящий элемент. Утверждается, что данный алгоритм в среднем работает за
Псевдокод
findMajorityElement(a, N, K)
while true
candidate = a[random(N)]
count = 0
for i = 0 to N - 1
if a[i] == candidate
count++
if count > N / K
return candidate
Доказательство
На каждом шаге мы берем случайный элемент. Проверка на мажорируемость выполняется за . Вероятность, что мы выбрали элемент "удачно" составляет . Тогда, в среднем, мы будем делать проверок. Итоговая сложность .