Вычисление сложности записи Big O для фрагмента кода

Не могли бы вы объяснить, как вычислить сложность Big O следующего сегмента:

i := n;
while i > 1 do
  begin
    for j:= i div 2 + 1 to i do
      begin
        k := 2;
        while n >= k do
          k := k * k
      end;
    i := i div 2
  end;

(Это Паскаль, но язык здесь не очень важен.) Правильный ответ: n * log (log (n)) , но я не знаю, как туда добраться.

0
nl ja de
Действительно n * log (log (n)) ? Я бы подумал n * log (n) ² .
добавлено автор BeniBela, источник
о, прямо сейчас, я вижу это.
добавлено автор BeniBela, источник
Это часть моего экзамена, и учитель отметил n * log (log (n)) как правильное решение.
добавлено автор user1934166, источник

1 ответы

Начните с внутренних циклов:

    k := 2;
    while n >= k do
      k := k * k

Это присваивает значения 2, 2 2 , 2 4 , 2 8 , ... до k , пока не достигнет п . Это O (log (log (n)), потому что, если мы будем называть число итераций m, оно повторяется до

22m > n   →   log(22m) > log(n)   →   log(log(22m)) > log(log(n))   →

→   m > log(log(n))   →   m = log(log(n)) + 1

затем

for j:= i div 2 + 1 to i do
  begin
    //O(log(log(n))
  end;

Это имеет i/2 итерации, поэтому O ((i/2) log (log (n)))

i := n;
while i > 1 do
  begin
   //(i/2) log(log(n))
    i := i div 2
  end;

Это имеет O (log (n)) итераций O ((i/2) log (log (n))), который суммируется с

  O( (n/2) log(log(n)) + (n/4) log(log(n)) + (n/8) log(log(n)) + (n/16) log(log(n)) + ... ) =
= O( (1/2 + 1/4 + 1/8 + 1/16 + ...)  n log(log(n)) ) =
= O( 0.1111111…2 n log(log(n)) ) =
= O( n log(log(n)) )

(0.11111 ... 2 = 1, как и 0.999 ... 10 = 1, но это не имеет значения в O() в любом случае)

2
добавлено