Асимптотически (большой-о-мудрый), вы не можете использовать бинарный поиск, чтобы улучшить наихудший случай, по причинам, приведенным выше моих. Однако, вот некоторые идеи, которые могут или не помогут вам на практике.
Для каждого целого, двоичный поиск его последнего вхождения.Как только вы его найдете, вы знаете, сколько раз он появляется в массиве, и может соответствующим образом обновлять ваши счета. Затем продолжите поиск с позиции, которую вы нашли.
Это выгодно, если у вас есть только несколько элементов, которые повторяются много раз, например:
1 1 1 1 1 2 2 2 2 3 3 3 3 3 3 3 3 3 3
Потому что вы будете делать только 3 бинарных поисков. Однако, если у вас есть много различных элементов:
1 2 3 4 5 6
Тогда вы будете делать O(n)
бинарные поиски, в результате чего в O(n log n)
сложности, так что хуже.
Это дает вам лучший лучший вариант и худший худший случай, чем ваш первоначальный алгоритм.
Можем ли мы сделать лучше? Мы могли бы улучшить худший случай, найдя последнее вхождение числа в позиции i
следующим образом: посмотрите на 2i
, затем на 4i
и т. Д., Пока значение в этих позициях одинаково. Если их нет, посмотрите на (i + 2i)/2
т.д.
Для примера рассмотрим массив:
i
1 2 3 4 5 6 7 ...
1 1 1 1 1 2 2 2 2 3 3 3 3 3 3 3 3 3 3
Мы смотрим на 2i = 2
, он имеет такое же значение. Мы смотрим на 4i = 4
, то же значение. Мы смотрим на 8i = 8
, различное значение. Мы возвращаемся к (4 + 8)/2 = 6
. Различное значение. Назад к (4 + 6)/2 = 5
. То же самое значение. Попробуйте (5 + 6)/2 = 5
, то же значение. Мы больше не ищем, потому что наше окно имеет ширину 1, поэтому мы закончили. Продолжить поиск с позиции 6
.
Это должно улучшить лучший случай, сохраняя наихудший случай как можно быстрее.
Асимптотически ничего не улучшается. Чтобы убедиться, что на практике это работает в среднем на практике, вам придется протестировать его.
Это не выглядит так, представьте случай, когда каждый элемент присутствует только один раз, поэтому любой элемент является действительным ответом. Но нет способа сказать, что это так, пока вы не проверили каждый элемент. – biziclop
Чтобы рассказать о среднем случае, вам нужно определить распределение вероятностей для возможных входов. Для таких алгоритмов, как quicksort, существует естественное распределение вероятности, которое можно использовать, но я не вижу, что вы будете использовать здесь. – interjay
Я разместил алгоритм, который использует O ((n/k) log k) зонды, где k - частота наиболее часто встречающегося целого. Это асимптотически оптимально в n и k. –