2009-10-13 2 views
12

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

Если медиана равна n, числа слева меньше n, а числа справа больше n. Однако массив не сортируется в левой или правой сторонах. Номера представляют собой любой набор различных чисел, заданных пользователем.

Проблема заключается в введении в Алгоритмы по Cormen, проблемы 9.3-7

+0

Если медиана находилась в местоположении n, вы ищете значения в местоположении n + 1 и местоположении n-1? – Polaris878

+1

Являются ли числовые бинарные числа или целые числа с фиксированной точкой? – outis

ответ

0

Собственно, ответ довольно прост. Все, что нам нужно сделать, - это выбрать k элементов с наименьшими абсолютными отличиями от медианы, движущейся от m-1 до 0 и m + 1 до n-1, когда медиана равна индексу m. Мы выбираем элементы, используя ту же идею, которую мы используем при объединении 2 отсортированных массивов.

+1

Но как мы их выбираем в O (n), учитывая, что элементы не сортируются в зависимости от их абсолютной разницы от медианной? –

-1

Если вы знаете, индекс медианы, который должен быть просто CEIL (array.length/2), может быть, тогда он просто должен быть процесс перечисления n (xk), n (x-k + 1), ..., n (x), n (x + 1), n ​​(x + 2), ... n (x + k) где n - массив, x - индекс медианы, k - количество соседей, в которых вы нуждаетесь. (Возможно, k/2, если вы хотите, чтобы общее количество k, а не k с каждой стороны)

+0

Это не работает. Медиана медианных алгоритмов DOESNT сортирует элементы. Для этого потребуется O (n log n), тогда как медианные медианы работают на O (n). – Steve314

+0

Ах, извинения. Я прочитал оригинальный вопрос в версии 2, где добавил, что он уже отсортировал его по порядку. – glasnt

-1

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

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

+2

Хотя верно, что O (k) есть O (1), когда k постоянна, если k -> n, то это становится O (n^2). Кроме того, как вы знаете, что k постоянна? Если это так, то нельзя также считать n постоянным? –

5

Средние медианы, вероятно, не помогают найти ближайших соседей, по крайней мере, для больших n. Правда, у вас есть каждый столбец из 5 разделенных вокруг медиана, но этого недостаточно для упорядочения информации для решения проблемы.

я просто рассматривать медиану как промежуточный результат, и лечить ближайшие сосед как проблема очередей приоритетов ...

После того как вы медиана от медианы медианы из-, держать ноту это значение.

Запустите алгоритм heapify для всех ваших данных - см. Wikipedia - Binary Heap. В сравнении, основывайте результат на различии относительно этого сохраненного медианного значения. Наивысшими приоритетами являются те, у которых самый низкий АБС (значение - медиана). Это берет O (n).

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

Пока k является константой, вы получаете медиана O (n) медианов, O (n) heapify и O (log n), получая O (n) в целом.

+1

Не сложность heapify O (nlogn)? – Anonymous

+3

Если вы сделаете это глупым способом (вставьте каждый элемент в свою очередь в первоначально пустую кучу), это O (n log n). Если вы используете алгоритм heapify, это O (n). См. Страницу wikipedia (раздел «Создание кучи») для более подробной информации. – Steve314

+0

Почему мы можем рассматривать k как константу? Что, если 'k == n'? – Yos

0

Вы уже знаете, как найти медиану в O (п)

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

from wikipedia

function findFirstK(list, left, right, k) 
if right > left 
    select pivotIndex between left and right 
    pivotNewIndex := partition(list, left, right, pivotIndex) 
    if pivotNewIndex > k // new condition 
     findFirstK(list, left, pivotNewIndex-1, k) 
    if pivotNewIndex < k 
     findFirstK(list, pivotNewIndex+1, right, k) 

не забудьте частный случай, когда к == п вернуть первоначальный список

0

В списке чисел L вы можете использовать сортировку без сравнения, такую ​​как сортировка радикса, а затем найти ближайших соседей k, рассматривая окна элементов k и исследуя конечные точки окна. Другой способ заявить «найти окно» - найти i, который минимизирует abs(L[(n-k)/2+i] - L[n/2]) + abs(L[(n+k)/2+i] - L[n/2]) (если k нечетно) или abs(L[(n-k)/2+i] - L[n/2]) + abs(L[(n+k)/2+i+1] - L[n/2]) (если k четный). Объединение корпусов, abs(L[(n-k)/2+i] - L[n/2]) + abs(L[(n+k)/2+i+!(k&1)] - L[n/2]). Простой способ определения минимума O (k) должен начинаться с i = 0, затем скользить влево или вправо, но вы должны иметь возможность найти минимум в O (log (k)).

Выражение, которое вы смирите, связано с преобразованием L в другой список, M, принимая разницу между каждым элементом из медианного.

m=L[n/2] 
M=abs(L-m) 

i минимизирует M[n/2-k/2+i] + M[n/2+k/2+i].

-1

Поскольку все элементы различны, могут быть самые два элемента с одинаковым отличием от среднего. Я считаю, что мне легче иметь 2 массива A [k] и B [k] индекс, представляющий абсолютную величину разницы от среднего. Теперь задача состоит в том, чтобы просто заполнить массивы и выбрать k элементов, прочитав первые k непустых значений массивов, читающих A [i] и B [i], перед A [i + 1] и B [i + 1]. Это можно сделать в O (n) времени.

+1

«выберите k элементов, прочитав первые k непустых значений массивов» - для этого массивы должны быть отсортированы. Сортировка этих массивов занимает время O (n log n). –

+0

@Windows programmer: только если вы делаете сравнение, основанное на сортировке. – outis

+1

Это работает, если только числа являются целыми числами – Anonymous

4
med=Select(A,1,n,n/2) //finds the median 

for i=1 to n 
    B[i]=mod(A[i]-med) 

q=Select(B,1,n,k) //get the kth smallest difference 

j=0 
for i=1 to n 
    if B[i]<=q 
    C[j]=A[i] //A[i], the real value should be assigned instead of B[i] which is only the difference between A[i] and median. 
     j++ 
return C 
+0

, так как значения в массиве B могут быть равны, вы должны убедиться, что j не больше k. В то же время, если вы описываете свой ответ в тексте, другие могут понять вас лучше. – meteorgan

17

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

+0

Вы должны брать модули чисел, прежде чем найти k-й порядок статистики. Я думаю, – iLoveCamelCase

+0

Если ваш список (1,2,10,11,12), запуск вашего алгоритма с помощью (k = 2) вернет (1,2) вместо (11,12) – Zvika

2

Вы можете решить проблему так:.

Вы можете найти медиану в O (N), вес гарантированы используя алгоритм O (n) nth_element.

Вы перебрать все элементы substutiting каждый с парой:

the absolute difference to the median, element's value. 

еще раз вы nth_element с п = к. после применения этого алгоритма вы гарантированно должны иметь k наименьших элементов в абсолютной разности сначала в новом массиве. Вы берете их индексы и СОВЕРШЕНО!

+0

Это то же самое, что и ответ @ HalPri, который был опубликован за год до вашего. –

+0

@JohnKurlak ok, я не читал его тогда, спасибо за указание – Shivendra

+1

Это лучше, чем ответ @ HalPri - @Shivendra использует 'absoulte difference', что устраняет проблему, указанную в моем комментарии к ответу @ HalPri – Zvika

Смежные вопросы