Мажорирующий элемент — различия между версиями
Никита (обсуждение | вклад) м (→Псевдокод) |
Никита (обсуждение | вклад) (→Доказательство) |
||
| Строка 26: | Строка 26: | ||
=== Доказательство === | === Доказательство === | ||
| + | |||
| + | На ''i-ом'' шаге выполняется следующий инвариант: если <tex>count > 0</tex>, то <tex>candidate</tex> - мажорирующий элемент на подмассиве <tex>a[0..i]</tex>, либо мажорирующего элемента на данном подмассиве не существует. Тогда на ''N-ом'' шаге <tex>candidate</tex> будет содержать мажорирующий элемент на всем массиве, т.к. гарантируется его существование. Покажем, что данный инвариант всегда выполняется. | ||
| + | |||
| + | Пусть данный инвариант выполняется на ''k-ом'' шаге. Тогда на ''(k+1)-ом'' шаге возможны 3 варианта: | ||
| + | # <tex>count == 0</tex>. Очевидно, что на подмассиве <tex>a[0..k]</tex> мажорирующего элемента не существует, так как все элементы разбились на пары. Тогда только <tex>a[k+1]</tex> может быть мажорирующим элементом. | ||
| + | |||
| + | # <tex>count > 0</tex> и <tex>a[k+1] == candidate</tex>. Если на подмассиве <tex>a[0..k]</tex> существует мажорирующий элемент, то он находится в <tex>candidate</tex>. Тогда, в силу равенства <tex>a[k+1]</tex> и <tex>candidate</tex>, если на подмассиве <tex>a[0..(k+1)]</tex> существует мажорирующий элемент, то он будет равен | ||
| + | |||
| + | # <tex>count > 0</tex> и <tex>a[k+1] != candidate</tex>. Если на подмассиве <tex>a[0..k]</tex> существует мажорирующий элемент, то он находится в <tex>candidate</tex>. | ||
== Обобщение на случай поиска элемента, встречающегося N/K раз == | == Обобщение на случай поиска элемента, встречающегося N/K раз == | ||
Версия 16:26, 24 мая 2013
Содержание
Формулировка задачи
Требуется в массиве длиной N найти элемент, встречающийся более N/2 раз. Гарантируется, что такой элемент существует.
Решение за 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 варианта:
- . Очевидно, что на подмассиве мажорирующего элемента не существует, так как все элементы разбились на пары. Тогда только может быть мажорирующим элементом.
- и . Если на подмассиве существует мажорирующий элемент, то он находится в . Тогда, в силу равенства и , если на подмассиве существует мажорирующий элемент, то он будет равен
- и . Если на подмассиве существует мажорирующий элемент, то он находится в .
Обобщение на случай поиска элемента, встречающегося 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
Доказательство
На каждом шаге мы берем случайный элемент. Проверка на мажорируемость выполняется за . Вероятность, что мы выбрали элемент "удачно" составляет . Тогда, в среднем, мы будем делать шагов. Итоговая сложность .