Во-первых, ваш алгоритм не O(sqrt(N))
, как вы игнорируете количество раз, вы разделите по каждому из проверяемых чисел. Если проверяемое число равно k
, количество делений до получения результата (по описанному выше методу) составляет O(log(k))
. Следовательно, сложность становится N/2 + (log(2) + log(3) + ... + log(sqrt(N)) = O(log(N) * sqrt(N))
.
Теперь, когда у нас это есть, алгоритм может быть улучшен. Обратите внимание, что при повторном разделении вы получите 1
для зарегистрированного номера k
только тогда, когда k^t <= N < 2 * k^t
, где t=floor(log_k(N))
.
То есть, если k^t <= N < 2 * k^(t+1)
. Обратите внимание на строгую <
с правой стороны.
Теперь, чтобы выяснить, t
, вы можете использовать метод Ньютона-Рафсона или серии Тейлора, чтобы получить логарифмы очень быстро, и указана степень сложности here. Назовем это C(N)
. Таким образом, сложность будет C(2) + C(3) + .... + C(sqrt(N))
. Если вы можете проигнорировать стоимость вычисления log
, вы можете получить это до O(sqrt(N))
.
Например, в приведенном выше случае для N = 8:
2^3 <= 8 < 2 * 2^3
: 1
floor(log_3(8)) = 1
и 8
не удовлетворяет 3^1 <= 8 < 2 * 3^1
: 0
floor(log_4(8)) = 1
и 8
не удовлетворяет 4^1 <= 8 < 2 * 4^1
: 0
4
Дополнительный входящий из номеров 5
, 6
, 7
и 8
как 8
t=1
для этих чисел.
Обратите внимание, что мы не должны проверить 3
и 4
, но я сделал так, чтобы проиллюстрировать этот момент. И вы можете проверить, что каждое из чисел в [N/2..N]
удовлетворяет вышеуказанному неравенству и, следовательно, необходимо добавить.
Если вы используете этот подход, мы можем устранить повторяющиеся деления и получить сложность до O(sqrt(N))
, если сложность вычисления логарифмов можно считать незначительной.
Примечание: 'N/2 + Проверка номера из (2, SQRT (N))' -> '(N + 1)/2 + Check Числа от (2, sqrt (N)) 'Пример' N == 3'. – chux