Подтвердить что ты не робот

Анализ Big-O для цикла

Мне нужно проанализировать этот цикл, среди прочего, и определить его время работы с использованием нотации Big-O.

for ( int i = 0; i < n; i += 4 )
    for ( int j = 0; j < n; j++ )
        for ( int k = 1; k < j*j; k *= 2 )`

Вот что я до сих пор:

for ( int i = 0; i < n; i += 4 ) = n

for ( int j = 0; j < n; j++ ) = n

for ( int k = 1; k < j*j; k *= 2 ) = log^2 n

Теперь проблема, к которой я прихожу, - это окончательное время цикла. Мое лучшее предположение - O (n ^ 2), однако я не уверен, что это правильно. Может ли кто-нибудь помочь?

Изменить: извините за О-О вещь. В моем учебнике используется "Big-Oh"

4b9b3361

Ответ 1

Прежде всего обратите внимание, что внешний цикл не зависит от остальных двух - он просто добавляет множитель (n/4)*. Мы рассмотрим это позже.

Теперь рассмотрим сложность

for ( int j = 0; j < n; j++ )
    for ( int k = 1; k < j*j; k *= 2 )

Мы имеем следующую сумму:

0 + log 2 (1) + log 2 (2 * 2) +... + log 2 (n * n )

Хорошо отметить, что log 2 (n ^ 2) = 2 * log 2 (n). Таким образом, мы перегруппируем сумму на:

2 * (0 + log 2 (1) + log 2 (2) +... + log 2 (n) )

Анализ этой суммы непросто, но посмотрите этот пост. Используя приближение Стерлинга, можно считать, что оно принадлежит O(n*log(n)). Таким образом, общая сложность O((n/4)*2*n*log(n))= O(n^2*log(n))

Ответ 2

  • В терминах j внутренний цикл равен O(log_2(j^2)) времени, но синус log_2(j^2)=2log(j), это фактически O(log(j)).
  • Для каждой итерации среднего цикла требуется время O (log (j)) (для выполнения внутренний цикл), поэтому нам нужно суммировать:

    sum {log (j) | j = 1,..., n-1} log (1) + log (2) +... + log (n-1) = log ((n-1)!)

И поскольку log((n-1)!) находится в O((n-1)log(n-1)) = O(nlogn), мы можем заключить, что средний средний цикл принимает операции O(nlogn).

  • Обратите внимание, что и средний, и внутренний цикл не зависят от i, поэтому получим полную сложность, мы можем просто умножить n/4 (число повторы внешнего цикла) со сложностью средней петли и получить:

    O (n/4 * nlogn) = O (n ^ 2logn)

Таким образом, общая сложность этого кода O(n^2 * log(n))

Ответ 3

Время Сложность цикла рассматривается как O (n), если переменные цикла увеличиваются/уменьшаются на постоянную величину (которая приведена в примерах ниже):

   for (int i = 1; i <= n; i += c) {  
        // some O(1) expressions
   }

   for (int i = n; i > 0; i -= c) {
        // some O(1) expressions
   }

Сложность времени вложенных циклов равна количеству раз, когда выполняется самый внутренний оператор. Например, следующие контуры образцов имеют сложную временную сложность O (n²):

for (int i = 1; i <=n; i += c) {
       for (int j = 1; j <=n; j += c) {
          // some O(1) expressions
       }
   }

   for (int i = n; i > 0; i += c) {
       for (int j = i+1; j <=n; j += c) {
          // some O(1) expressions
   }

Время Сложность цикла считается O (logn), если переменные цикла делятся/умножаются на постоянную величину:

for (int i = 1; i <=n; i *= c) {
       // some O(1) expressions
   }
   for (int i = n; i > 0; i /= c) {
       // some O(1) expressions
   }

Теперь мы имеем:

for ( int i = 0; i < n; i += 4 ) <----- runs n times
    for ( int j = 0; j < n; j++ ) <----- for every i again runs n times
        for ( int k = 1; k < j*j; k *= 2 )` <--- now for every j it runs logarithmic times.

Таким образом, сложность O (n²logm), где m равно n², которое можно упростить до O (n²logn), потому что n²logm = n²logn² = n² * 2logn ~ n²logn.