Мой инстинкт - выбрать 100 лучших элементов из списка (гораздо дешевле, чем сортировать, используйте ваш любимый вариант QuickSelect).Запустите их через фильтр, получив n
успехов и 100-n
сбоев.Если n < 100
, то повторите, выбрав 100-n
элементов в верхней части остальной части списка:
k = 100
while (k > 0):
select top k from list and remove them
filter them, yielding n successes
k = k - n
Все хорошо, это выполняется во времени, пропорциональном длине списка, так как каждый шаг выборавыполняется в это время, и количество требуемых шагов выбора зависит от частоты успеха фильтра, но не напрямую от размера списка.
Я ожидаю, что это имеет некоторые плохие случаи.Если почти все элементы не проходят фильтрацию, это значительно медленнее, чем просто сортировка, поскольку в итоге вы выберете тысячи раз.Таким образом, вы можете захотеть, чтобы некоторые критерии выручили, если он выглядит плохо, и вернулись к сортировке всего списка.
У него также есть проблема, заключающаяся в том, что он, вероятно, выполнит большое количество маленьких выборок в конце, так какмы ожидаем, что k будет уменьшаться экспоненциально, если критерии фильтра не связаны с критериями сортировки.Таким образом, вы могли бы улучшить его, выбрав несколько больше чем k элементов на каждом шаге.Скажем, k делится на ожидаемую частоту успеха фильтра плюс небольшую константу.Ожидание, основанное на прошлой производительности, если нет знания предметной области, которое вы можете использовать, чтобы предсказать его, и небольшую константу, выбранную экспериментально, чтобы избежать досадно большого количества шагов, чтобы найти несколько последних элементов.Если на каком-либо этапе вы получите больше элементов, которые прошли фильтр, чем число, которое вы все еще ищете (т. Е. N> k), то выберите верхний k из текущей серии успехов, и все готово.
Поскольку QuickSelect дает вам верхнее k без сортировки этих k, вам нужно будет выполнить окончательную сортировку из 100 элементов, если вам нужны верхние 100 по порядку.