Большая-О сложность куска кода
у меня есть вопрос в разработке алгоритма о сложности. В этот кусок кода и я должен вычислить сложность этого кода.
Псевдо-код:
for(i=1;i<=n;i++){
j=i
do{
k=j;
j = j / 2;
}while(k is even);
}
я попробовал этот алгоритм для некоторых чисел. и я получил разные результаты. например, если n = 6, Этот вывод алгоритма выглядит следующим образом
i = 1 -> executes 1 time
i = 2 -> executes 2 times
i = 3 -> executes 1 time
i = 4 -> executes 3 times
i = 5 -> executes 1 time
i = 6 -> executes 2 times
он не имеет регулярной темы, как я должен вычислить это?
5 ответов:
верхняя граница, заданная другими ответами, на самом деле слишком высока. Этот алгоритм имеет время выполнения O(n), которое является более жесткой верхней границей, чем O(n*logn).
доказательство: давайте подсчитаем, сколько всего итераций будет выполнять внутренний цикл.
внешний цикл работает
nраза. Внутренний цикл выполняется по крайней мере один раз для каждого из них.
- даже
iвнутренний цикл выполняется как минимум в два раза. Это происходитn/2раза.- для
iделится на 4, внутренний цикл выполняется не менее трех раз. Это происходитn/4раза.- на
iделится на 8, внутренний цикл выполняется не менее четырех раз. Это происходитn/8раза.- ...
таким образом, общее количество запусков внутреннего цикла составляет:
n + n/2 + n/4 + n/8 + n/16 + ... <= 2nобщее количество итераций внутреннего цикла находится между
nи2n, т. е. это Θ(n).
вы всегда предполагаете, что вы получаете худший сценарий на каждом уровне.
теперь вы перебираете массив с N элементами, поэтому мы начинаем сO(N)уже.
теперь давайте скажем вашiвсегда равнаXиXвсегда даже (помните, в худшем случае каждый раз).
сколько раз нужно разделитьXby2и1? (это единственное условие для четных чисел, чтобы остановить деление, когда они достигают 1).
другими словами, нам нужно решите уравнениеX/2^k = 1что этоX=2^kиk=log<2>(X)это делает наш алгоритм взятьO(n log<2>(X))шаги, которые можно легко записать какO(nlog(n))
для такого цикла мы не можем разделить количество внутреннего цикла и внешнего цикла - > переменные помечены!
таким образом, мы должны просчитать все шаги.
фактически, для каждой итерации внешнего цикла (on
i), у нас будет1 + v_2(i) stepsздесь
v_2это 2-адическая оценка (см. например:http://planetmath.org/padicvaluation), что соответствует силе2в разложении в простом фактореi.так что если мы добавим шаги для всех
iмы получаем общее количество шагов :n_steps = \sum_{i=1}^{n} (1 + v_2(i)) = n + v_2(n!) // since v_2(i) + v_2(j) = v_2(i*j) = 2n - s_2(n) // from Legendre formula (see http://en.wikipedia.org/wiki/Legendre%27s_formula with `p = 2`)мы тогда видим, что число шагов и ровно:
n_steps = 2n - s_2(n)как
s_2(n)- это сумма цифрnбазовый2, это незначительно (самое большееlog_2(n)начиная с цифры в базе2это 0 или 1 и как есть самое большееlog_2(n)цифр) по сравнению сn.так сложность вашего алгоритма эквивалентна
n:n_steps = O(n)что это не the
O(nlog(n))заявлено во многих других решениях, но в меньшем количестве!
давайте начнем с худшего случая:
Если вы продолжаете делить с 2 (Интеграл) вам не нужно останавливаться, пока вы добраться до 1. в основном делая количество шагов зависит от ширины бита, что-то, что вы узнаете, используя логарифм двух. таким образом, внутренняя часть-log n. внешняя часть, очевидно, n, поэтому
N log Nобщий.
A
doпетли половинкиjдоkстановится нечетным.kизначально является копиейj, который является копиейi, так чтоdoработает 1 + силу2, который делитi:
- i=1 нечетно, поэтому он делает 1 проход через
doцикл- i=2 делится на 2 один раз, так что 1+1,
- i=4 делит дважды на 2, поэтому 1+2 и т. д.
это составляет не более 1 + log (i)
doвыполнение (логарифм с базой 2).The
forцикл работаетiС 1 поn, так что верхняя границаnраза (1+зарегистрируйте N), который является o(n записей N).
Comments