Анализ цикла for

Рассмотрим этот фрагмент кода

int sum = 0;
for( int i = 1; i <= n*n; i = i*2 ){
   sum++ ;
}

Как сделать быстрый правильный анализ, чтобы получить порядок роста времени работы в худшем случае?

Как изменение оператора приращения на i = i * 3 вместо i = i * 2 меняет время работы в наихудшем случае?

И влияет ли на наш анализ изменение оператора сравнения на < вместо <=?


person iartist93    schedule 21.09.2014    source источник
comment
я не понимаю вашего вопроса... Вы спрашиваете, что делает цикл и как он будет себя вести, если заменить i*2 на i*3 и ‹ на ‹= ? кстати... мы здесь не для того, чтобы делать твою домашнюю работу...   -  person Kraal    schedule 21.09.2014
comment
возможный дубликат Простое английское объяснение Big O   -  person Whymarrh    schedule 21.09.2014
comment
я хочу получить порядок роста времени работы в худшем случае   -  person iartist93    schedule 21.09.2014


Ответы (3)


int sum = 0;
for( int i = 0; i <= n*n; i = i*2 ){
   sum++ ;
}

В нынешнем виде это бесконечный цикл, который никогда не остановится, поскольку i никогда не меняется. Поскольку сложность определена только для алгоритмов, которые по определению должны завершаться за конечное время, для этого фрагмента она не определена.

Однако, если вы измените код на следующий:

int sum = 0;
for( int i = 1; i <= n*n; i = i*2 ){
   sum++ ;
}

Мы можем проанализировать сложность следующим образом:

Пусть цикл выполняется k - 1 раза и завершается при kth обновлении i. Поскольку лучше быть избыточным, чем неясным, вот что происходит:

Init(1) -> test(1) -> Loop(1) [i = 1]->
Update(2) -> test(2) -> Loop(2) [i = 2]->< br> ...
Update(k - 1) -> test(k - 1) -> Loop(k - 1) [i = 2 ^ (k - 2)] ->
Update(k) -> test(k)->STOP [Тест не пройден, так как i становится 2 ^ (k - 1)]

Где Update(k) означает kth обновление (i = i * 2).

Поскольку приращения в i таковы, что в цикле pth (или, что то же самое, после pth updation) значение i будет 2 ^ (p - 1), мы можем сказать, что при завершении:

2 ^ (k - 1) > (n * n)

Если говорить подробно, мы остановились на k-м обновлении. Каким бы ни было значение i, оно было бы больше (n * n), иначе мы бы зациклились на kth. Принимая log base 2 с обеих сторон:

 k ~ 2 * log(n)

Это означает, что k равно O(log(n)).

Соответственно, цикл выполняется O(log(n)) раз.

Вы можете легко расширить эту идею до любого предела (скажем, n*n*n) и любых приращений (i*3, i*4 и т. д.).

На сложность Big O не повлияет использование < вместо <=

person axiom    schedule 21.09.2014
comment
Спасибо @axiom :) понял .. но интересно, есть ли метод анализа - person iartist93; 21.09.2014

На самом деле этот цикл является бесконечным циклом.

i=0
i=i*2  //0*2=0

Так что эта петля никогда не закончится. Сделайте i=1, чтобы получить количество степеней от 2 до n^2, а не суммы.

person Pratyush Khare    schedule 21.09.2014
comment
это должен быть комментарий, а не ответ. - person Haris; 21.09.2014
comment
Кому-то трудно комментировать с менее чем 50 повторениями - person Damian; 21.09.2014
comment
Я не могу комментировать. У меня недостаточно привилегий. Спасибо @Damian за указание. - person Pratyush Khare; 21.09.2014
comment
Извините, я изменил его на i=1 no 0, это моя вина, извините! - person iartist93; 21.09.2014

для любого цикла, чтобы проанализировать его. Вы должны увидеть 2 вещи. условие, которое заставит его выйти, и итерация, применяемая к переменной, используемой в условии.

для вашего кода. Вы можете заметить, что цикл останавливается, когда i переходит от 0 к n * n (n ^ 2). и переменная i увеличивается как i = i*2. поскольку i увеличивает i таким образом, цикл будет выполняться log (n ^ 2) раз. это вы можете увидеть, взяв пример значения n ^ 2, например 128, а затем повторяя его вручную один за другим.

person Haris    schedule 21.09.2014