найти медиану в O (войти n) - PullRequest
       1

найти медиану в O (войти n)

5 голосов
/ 21 октября 2011

Вопрос в том, как мы можем найти медиану принимающего потока целочисленных значений (например, для 12, 14, 252, 243, 15 медиана равна 15) в O (log N) , где Nэто количество значений.Обратите внимание, что у нас есть поток целочисленных значений, поэтому, получая каждое значение, мы должны повторно найти медиану.

Пример:

  | Input | median
1 |   12  |   12
2 |   14  |   13 = (12+14)/2
3 |   252 |   14
.
.
.

PS: пример использования этогоАлгоритм может быть фильтрация изображения.

Ответы [ 3 ]

14 голосов
/ 21 октября 2011

Хорошо, с обновлением вопроса, так что цель ясна (не просто найти медиану, но заново находить медиану каждый раз, когда вы получаете новое число), я думаю, что есть способ.

Я бы начал с пары куч: максимальная куча и минимальная куча. Мин-куча будет содержать числа больше, чем медиана, а максимальная куча - числа меньше медианы. Когда вы получаете первый номер, это ваша медиана. Когда вы получаете второе, вы вставляете меньшее из двух в максимальную кучу, а большее из двух в минимальную кучу. Медиана - это среднее из наименьшего значения в минимальной куче и наибольшее в максимальной куче.

Наряду с двумя кучами вам потребуется хранилище для единственного целого числа, которое будет текущей медианой, когда вы получили нечетное количество входных данных. Вы заполняете это довольно просто: если вы получаете ввод с полным списком, вы в основном сортируете эти два элемента (новый номер и старое медиану) и вставляете меньшее в кучу для меньших элементов и большее в кучу для более крупных предметов. Тогда ваша новая медиана будет средним основанием этих двух куч (и вы пометите другое хранилище как пустое).

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

По крайней мере, если память служит, извлечение / вставка в кучу должно быть O (log N). Я считаю, что все остальное должно быть постоянной сложности.

4 голосов
/ 21 октября 2011

(Я предполагаю, что вы используете алгоритм, который, учитывая n существующих чисел и одно новое число, займет логарифмическое время, чтобы найти медиану новой коллекции n + 1 чисел, так что общее время выполнения для добавления n чисел будет O (n lg n) .)

Вероятно, уже есть названный алгоритм для этого, но вот моя идея: сохранить красно-черное дерево, в которое вы вставляете числа по мере их поступления. В каждом узле, в дополнение к самому числу и указателям дочернего / родительского, вы храните целое число, которое сообщает количество узлов, которые существуют под этим узлом (включая сам узел, для удобства). Я совершенно уверен, что эта информация может обновляться в логарифмическом времени при каждой операции вставки, даже когда требуется поворот дерева. С этой информацией, встроенной в дерево, определение медианы может быть выполнено за логарифмическое время, если вы также отслеживаете количество узлов в дереве.

(Это может быть немного слишком высокоуровневое описание; дайте мне знать, если вам нужно больше подробностей.)

2 голосов
/ 21 октября 2011

Алгоритм выбора Хоара (он же быстрый выбор) может сделать это за среднее время O (n).

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...