Из моего комментария: «Это тесно связано с количеством, повсеместным в оценке академической производительности, индексом Хирша, более известным как -индексчас . Вкратце она определяется как число публикаций приходится таким образом, что каждый из них имеет по крайней мере час цитат (самый большой такой час ).часчасчас
Единственное, чем отличается ваша проблема, это то, что вас будет интересовать не только количество публикаций, удовлетворяющих этому критерию, но и количество их цитирований , но это тривиальная модификация. Данные уже есть, оригинальный алгоритм просто сбрасывает их.
Общепринятый расчет довольно прост и согласуется с ответом Каролис Юоделе .
Обновление: в зависимости от размера и характера ваших данных, возможно, стоит изучить методы, которые частично сортируют массив путем фильтрации данных выше и ниже центральной точки (на ум приходит быстрая сортировка). Затем, в зависимости от того, слишком мало или слишком много, отрегулируйте опору и повтор на подмножестве, которое его содержит, и так далее. Вам не нужен порядок между элементами выше , и уж точно не между элементами ниже этого. Так, например, как только вы нашли все элементы, большие или равные h 1 и их меньше h 1 , вам не нужно снова прикасаться к этому подмножеству, просто добавьте к нему. Это преобразует рекурсию, присущую быстрой сортировке, в хвостовую рекурсию и, таким образом, может быть переписано как цикл.часчас1час1
Мой Haskell немного заржавел, но это должно сделать то, что я описал выше, и, кажется, работает. Надеюсь, что это может быть понято до некоторой степени, я рад предоставить дополнительные объяснения.
-- just a utility function
merge :: [a] -> [a] -> [a]
merge [] ys = ys
merge (x:xs) ys = x : merge xs ys
-- the actual implementation
topImpl :: [Int] -> [Int] -> [Int]
topImpl [] granted = granted
topImpl (x:xs) granted
| x == (1 + lGreater + lGranted) = x : merge greater granted
| x > (1 + lGreater + lGranted) = topImpl smaller (x : merge greater granted)
| otherwise = topImpl greater granted
where smaller = [y | y <- xs, y < x]
greater = [y | y <- xs, y >= x]
lGreater = length greater
lGranted = length granted
-- starting point is: top of whole array, granted is empty
top :: [Int] -> [Int]
top arr = topImpl arr []
Идея состоит в granted
том, чтобы собрать то, что, как вы знаете, обязательно примет участие в результате, а не сортировать его дальше. Если greater
вместе с x
припадками нам повезло, в противном случае нам нужно попробовать с меньшим подмножеством. (Стержень x
просто все , что случилось с первым пунктом подсписка , который в настоящее время рассматривается.) Следует отметить , что значительное преимущество против принятия крупнейших элементов , один за другим, что мы делаем это на блоках среднего размера и не нужно сортировать их дальше.г е м а я п я п г/ 2
Пример:
Давайте возьмем ваш набор [1,3,4,1,3,6]
.
x = 1
, granted = []
, greater = [3,4,1,3,6]
. Ой, мы встречаемся с патологическим случаем, когда стержень слишком мал (на самом деле настолько мал, что smaller
пуст) прямо на первом шаге. К счастью, наш алгоритм готов к этому. Он сбрасывает x
и пытается снова с greater
одним.
x = 3
, granted = []
, greater = [4,3,6]
. Вместе они образуют массив длиной 4, но у нас только это ограничено снизу 3, так что это слишком много. Повторите в greater
одиночку.
x = 4
, granted = []
, greater = [6]
. Это дает массив из 2 элементов ≥ 4 каждый, кажется, мы могли бы использовать еще для некоторых из них. Сохраните это и повторите smaller = [3]
.
x = 3
, granted = [4,6]
, greater = []
. Это вместе дает массив из 3 элементов ≥ 3 каждый, поэтому у нас есть решение, [3,4,6]
и мы можем вернуться. (Обратите внимание, что перестановка может варьироваться в зависимости от порядка ввода, но всегда будет содержать максимально возможные термины, никогда [3,3,6]
или [3,3,4]
для вашего примера.)
(Кстати, обратите внимание, что рекурсия действительно просто свернулась в цикл.) Сложность несколько лучше, чем быстрая сортировка из-за многих сохраненных сравнений:
n - 1
O ( журналн )O ( n )
NO ( n2)
В приведенном выше коде есть несколько ненужных сравнений, например, вычисление smaller
того, нужен он нам или нет, их можно легко удалить. (Я думаю, что ленивая оценка позаботится об этом, хотя.)