Похоже, вам нужно использовать алгоритм адаптивной сортировки .
«Алгоритм сортировки попадает в адаптивное семейство сортировки, если он использует существующий порядок во входе. Он извлекает выгоду из предвзятости во входной последовательности или ограниченного количества нарушений для различных определений мер беспорядка и сортируется быстрее. Адаптивная сортировка обычно выполняется путем изменения существующих алгоритмов сортировки ». - Статья Википедии, связанная выше.
Примеры включают сортировку вставки и Timsort; более подробно см. статью выше. Обратите внимание, что в Java 8 Arrays.sort(Object[])
библиотечный метод использует модифицированный Timsort.
Я не знаю ни одного опубликованного алгоритма, который касается конкретных требований вашего примера, но вот идея:
-
Выполните классическое объединение на двух входных списках L1 и L2:
- Когда вы объединяете пару объектов и меняете ключи, которые определяют порядок, поместите объединенный объект во временный список A.
- В противном случае объекты будут помещены во временный список B ... который останется упорядоченным.
-
Сортировка временного списка A.
-
Списки слияния A и B.
При условии, что:
- длины исходных списков L1 и L2 являются M & N соответственно, и
- количество объединенных объектов, чьи ключи изменены, R (что меньше max (M, N)),
то общая сложность - O (M + N + RlogR). Если R мало относительно M + N, то это должно быть улучшением.
В вашем примере каждый случай, когда есть совпадение между элементами во входных списках , скорее всего, перемещает элемент в порядке. Если он перемещает элемент, он переместится на более поздний порядок (и никогда ранее). Таким образом, другая идея состоит в том, чтобы выполнить трехстороннее слияние между исходными 2 списками и очередью приоритетов. Когда вы получаете совпадение, вы объединяете счетчики и добавляете результат в очередь приоритетов.
Сложность похожа на предыдущую, но вы избегаете дополнительного прохода для объединения списков. А также RlogR
становится RlogA
где средний размер очереди приоритетов.
Имейте в виду, что меня особенно интересует случай, когда R приблизительно равен max (M, N), а также M == N.
(Вы не указали это в своем вопросе! И на самом деле для R не имеет значения> min (M, N)!)
В этом случае, возможно, просто используйте очередь приоритетов в качестве инкрементного сортировщика. Бросьте все объединенные записи и все записи, которые не могут быть объединены в очередь, и потяните наши записи, если у них есть ключ / счет, который меньше, чем текущие главы этих двух списков. Предполагая, что M и N - длины списка, а A - средний размер очереди приоритетов, тогда сложность max (M, N) * log A). Будет ли это улучшение простого повторного сортировки, будет зависеть от того, будет ли среднее значение A значительным (в терминах Big O) меньше, чем max (M, N). Это будет зависеть от входных данных ... и функции слияния.
Число (N) меняется, но типично 256-1000. Возможно, целых 10 000 человек.
Для списков этого типичного размера вы находитесь на том уровне, где анализ сложности не будет полезен. Но также вы находитесь на том уровне, где оптимизация становится бессмысленной ... если вы не выполняете операцию много, много раз или в узком «временном бюджете».
Все это очень приблизительно, и мои математики в лучшем случае «отрывочны».
Правильное исследование потребует сотни часов исследований, кодов, тестов, тестов, анализа различных альтернатив ... и мы, вероятно, все равно получим ответ, что это зависит от размера и распределения набора входных данных.