нахождение наименьших k элементов в массиве в O (k)

12

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

Я обсуждал эту проблему с некоторыми друзьями, но никто не мог найти решение; любая помощь будет оценена!

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

Идан
источник
4
Как насчет использования мини-кучи?
Шир
1
Посмотрите на k-skyband и top-k вычисления. В статье cs.sfu.ca/~jpei/publications/subsky_tkde07.pdf есть хороший обзор соответствующей литературы.
Андрас Саламон
1
Шир, я изучил идею мини-кучи. однако, для того, чтобы вывести k наименьших чисел в минимальной куче, нужно время O (klogn), а не O (k), как требуется
Idan
4
@idannik: Как вы думаете, почему требуется чтобы найти k наименьших элементов в минимальной куче? Ω(klogn)k
Кристоффер Арнсфельт Хансен
8
Я не думаю, что это исследовательский уровень. Это похоже на задание. Где вы его нашли?
Каве

Ответы:

24

Предварительно обработать массив из значений за время O ( n ) :nO(n)

  • in
  • пока i>2
    • Вычислить медиану из A [ 1 .. я ] во время O ( я )mA[1..i]O(i)
    • разделить на A [ 1 .. i / 2 - 1 ] m и A [ i / 2 + 1 .. i ] m одновременно.A[1..i]A[1..i/21]mA[i/2+1..i]m
    • ii/2

Общее время предвычисления находится в пределах O(1+2+4+...+n)O(n)

Ответьте на запрос для наименьших элементов в A за время O ( k ) :kAO(k)

  • llog2k
  • выберите -й элемент x из A [ 2 l . .2 л + 1 ] за время O ( 2 л ) O ( k )(k2l)xA[2l..2l+1]O(2l)O(k)
  • перегородка по х в то же времяA[2l..2l+1]x

содержит k наименьших элементов.A[1..k]k

Ссылки:

  • В 1999 году Дор и Цвик разработали алгоритм для вычисления медианы из элементов за время в 2,942 n + o ( n ) сравнений, что дает алгоритм выбора k- го элемента из n неупорядоченных элементов менее чем за 6 n сравнений.n2.942n+o(n)kn6n
Джереми
источник
1
Я предполагаю, что внешний цикл должен быть «для i в ». Отличается ли ваш алгоритм от ответа Ювала Фильмуса? {2lgn,,4,2,1}
Раду GRIGore
2
Это обобщение моего алгоритма на произвольное . В нем также изложены некоторые детали реализации, которые (намеренно) были исключены из моего ответа. n
Юваль Фильмус
3
@YuvalFilmus Вы хотите сказать своим комментарием, что мой ответ неэтично близок вашему? Это решение пришло мне в голову, когда я рассмотрел вопрос. Я видел, что вы опубликовали похожую статью, но нашел ее неясной, поэтому я написал свою собственную (в отличие от вашей основной правки). В конечном итоге важно качество ответов в системах, а не то, кто их написал, а значки и репутация - это только стимулы, а не цели сами по себе.
Джереми
4
@ Джереми Совсем нет; Просто эти два решения одинаковы (но ваше работает для произвольного ), и что я не уточнил детали на случай, если это на самом деле домашнее задание. n
Юваль Фильмус
2
Ох :( Извините за это тогда. (Хотя я все еще думаю, что предоставление полных ответов будет приоритетом над подозрениями при назначении)
Джереми
14

Для простоты предположим, что . Используйте алгоритм линейного выбора времени, чтобы найти элементы в позициях 2 m - 1 , 2 m - 2 , 2 m - 3 , , 1 ; это занимает линейное время. Для данного k найти t таким, что 2 t - 1k 2 t ; обратите внимание, что 2 t2 k . Отфильтровать все элементы ранга не более 2 тn=2m2m1,2m2,2m3,,1kt2t1k2t2t2k2tи теперь используйте алгоритм линейного выбора времени, чтобы найти элемент в позиции за время O ( 2 t ) = O ( k ) .kO(2t)=O(k)

Пояснение: Может показаться, что предварительная обработка занимает время , и это действительно так, если вы неосторожны. Вот как выполнить предварительную обработку за линейное время:Θ(nlogn)

while n > 0:
  find the (lower) median m of A[0..n-1]
  partition A in-place so that A[n/2-1] = m
  n = n/2

Разделение на месте выполняется как в быстрой сортировке. Время работы является линейным в , и, следовательно, линейным. В конце концов, массив A удовлетворяет следующим свойством: для каждого к , A [ 0 .. п / 2 K - 1 ] состоит из п / 2 к наименьших элементов.n+n/2+n/4++1<2nAkA[0..n/2k1]n/2k

Юваль Фильмус
источник
1
Естественно. Если массив отсортирован, вы можете решить это в без предварительной обработки. Возможно, вам неизвестен алгоритм линейного выбора времени, который может найти k- й по величине элемент за время O ( n ) ? O(1)kO(n)
Юваль Фильмус
4
lognnlogn
3
@ AndrásSalamon: Если вы прочитаете ответ Джереми (который выглядит для меня почти так же, как этот), вы увидите, что сначала вы обрабатываете весь массив, затем первую половину и так далее.
Раду GRIGore
3
n+n/2+n/4++1<2n
5
Кстати, этот алгоритм фигурирует как подпрограмма в моем ответе на предыдущий вопрос: cstheory.stackexchange.com/questions/17378/…
Дэвид Эппштейн
0

kk

jbapple
источник
1
k
2
Понимаю. Моя ошибка.
Jbapple