По сложности задачи
Поскольку запрашивается точный счет (вместо того, чтобы спрашивать, включены ли хотя бы x входы),проблема очень ясна O(n)
:
- нужно посетить каждый отдельный вход, и,
- работа для каждого входа не зависит от n (в то время как работа для данного входаможет варьироваться в зависимости от конкретного значения ввода, объем работы [для этого ввода] не меняется, если количество входов изменяется.)
Мы, безусловно, можем реализовать неоптимальные алгоритмыкоторый, например, [излишне] будет посещать все другие входные данные, когда каждый вход обрабатывается, что делает его реализацией O (n ^ 2), но это, конечно, глупо.
Это утверждается, вопросыпоэтому, вероятно, о ...
уловках, которые сделают реализацию быстрее
Следует отметить, что, хотя такие уловки могут существовать, сложность алгоритма / проблемыостается заглушкойизначально при O (n).
Трюк 1: Лучшее хранилище для входных данных
К сожалению, этот вопрос указывает на то, что входные данные поступают от именованных переменных и что стоимость любогопреобразование входных данных [для обеспечения более быстрого счета] должно быть принято во внимание для оценки общей производительности алгоритма.Хотя в конечном итоге это зависит от базового языка, времени выполнения и т. Д., Необходимость учета стоимости преобразования весьма вероятно осуждает любой алгоритм, основанный на альтернативном хранилище, медленнее, чем решения, которые сохраняют входные данные как есть.
Уловка2: закорачивает оценку
Идея состоит в том, чтобы вернуть false
как можно скорее (или вскоре после этого) как
- текущее число входов, которые включеныбольше X число (или, если мы подсчитываем количество отключенных входов, когда этот счет превышает (n - X))
- количество входов, оставшихся для тестирования, плюс текущее количество входоввключено меньше X. (или что-то подобное в случае подсчета отключенных входов).
Этот трюк является относительно простым, но дополнительные затраты для вычисления значений, необходимых в началетесты выхода могут компенсировать выигрыш, полученный при [статическом] раннем выходе.
Трюк 3: использовать обратную логику : подсчитать количество входовВыкл, а не они включены.(или подсчитайте и то и другое).
Стоимость / выгода от этого подхода зависит как от количества входных данных для проверки (X вопроса), так и от статистической информации, которую мы можем иметь о входных данных (это число навходы в данный момент времени относительно равномерно распределены, или мы имеем тенденцию включать (или выключать) только несколько входов.
Решение , предложенное Крисом Ачесоном , обеспечивает базовую линию дляиспользование как уловки 2, так и уловки 3. Если предположить, что мы могли бы сделать несколько предположений о распределении состояния входных данных, дополнительные «улучшения производительности» этой базовой линии были бы обусловлены такими «априорами»: некоторая быстрая эвристика была выполнена до подсчетавходные данные сами по себе определяют, какое состояние мы должны рассчитывать (включено или выключено или оба), какое ограничение мы должны проверять и т. д., и переходить к соответствующим «версиям» алгоритма.
Также возможны дополнительные усиления, если мы знаем индивидуальную вероятность того, что данный вход будет включен или выключен, как мы тогда проверили быr наиболее (или наименее) вероятных в первую очередь, чтобы быстро добраться до нашего «значения короткого замыкания».
О «сложном» для этих оптимизированных алгоритмов наилучшем / худшем случае
Предполагая, что
- количество входов, которые включены в данный момент времени, равномерно распределено
- все входы имеют 50% -ное изменение включения в данный момент времени
- X случайно выбирается между 1 и n
Комбинация Трюков # 2 и # 3 может составлять в среднем O(X/2)
(мне нужно сделать математику, но это кажется правильным).Однако я думаю, что было бы разумнее говорить в терминах number of operations
относительно X и / или n, а не злоупотреблять O-нотацией ...
Предполагая, что все операции примерно одинаковы по стоимости
- Инициализация счетчика или переменной
- Проверка ввода или переменной
- сложение или вычитание
- и т. Д.
Это проще, а также большеточное вычисление общего числа операций, необходимых для выполнения данного алгоритма, и, следовательно, использование таких подсчетов для различных наилучших / худших / средних случаев, чтобы помочь определиться с конкретными алгоритмами.
Чтобы проиллюстрировать это, наивная реализация, которая простобудет систематически подсчитывать все входные данные и сравнивать только счетчик в конце, иметь сложность O (n) и завершаться во всех случаях примерно за 1 + 2 * n + 1 операций.Такой алгоритм может оказаться в целом лучше, чем более изящный алгоритм, который, скажем, O (X), O ((X + n) / 2) и O (n) в лучшем, среднем и худшем случаях соответственно, вполне может использовать операции X * 3, (X + n) * 1.5 и n * 3 в этих же случаях.