Análisis asintótico de tres bucles for anidados interdependientes

El fragmento de código que voy a analizar está a continuación:

int sum = 0;
for (int i = 0; i < n; i++)
   for (int j = 0; j < i * i; j++)
      for (int k = 0; k < j; k++)
         sum++;

Sé que el primer bucle es O (n) pero eso es todo lo que he llegado. Creo que el segundo ciclo puede ser O (n ^ 2) pero cuanto más lo pienso, menos sentido tiene. Cualquier orientación sería muy apreciada.

preguntado el 05 de febrero de 12 a las 01:02

4 Respuestas

El primer ciclo se ejecuta n veces. Cada vez, el valor i crece. Para cada uno de esos i, el segundo ciclo se ejecuta i*i veces. Eso significa que el segundo ciclo se ejecuta 1*1 + 2*2 + 3*3 + ... + n*n veces.

Esta es una suma de cuadrados, y la fórmula para esto es bien conocido. Por lo tanto, tenemos el segundo ciclo ejecutándose (n(1 + n)(1 + 2 n))/6 veces.

Por tanto, sabemos que en total habrá (n(1 + n)(1 + 2 n))/6 valores de j, y que para cada uno de estos el tercer ciclo se ejecutará 1 + 2 + ... + j = j(j+1)/2 veces. En realidad, calcular cuántas veces se ejecuta el tercer ciclo en total sería muy difícil. Afortunadamente, todo lo que realmente necesita es un límite superior mínimo para el orden de la función.

Sabes que para cada uno de los (n(1 + n)(1 + 2 n))/6 valores de j, el tercer ciclo se ejecutará menos que n(n+1)/2 veces. Por tanto, se puede decir que la operación sum++ ejecutará menos de [(n(1 + n)(1 + 2 n))/6] * [n(n+1)/2] veces. Después de algunos cálculos mentales rápidos, eso equivale a un polinomio de grado máximo 5, por lo tanto, su programa es O(n^5).

Respondido 05 Feb 12, 06:02

int sum = 0;                  
for (int i = 0; i < n; i++)            // Let's call this N
   for (int j = 0; j < i * i; j++)     // Let's call this M
      for (int k = 0; k < j; k++)      // Let's call this K
         sum++;

N es el número de pasos de todo el programa, M es el número de pasos que hacen los dos bucles internos y, por último, K es el número de pasos que hace el último bucle.

Es fácil ver que K = j, se necesitan j pasos para hacerlo.

Then M = Sum(j=0,i^2,K) = Sum(j=0, i^2, j)

(El primer parámetro es el iterador, el segundo es el límite superior y el último parámetro es lo que estamos agregando)

En realidad, esto es ahora una suma de n números para i * i. Lo que significa que podemos aplicar la fórmula ((n + 1) * n) / 2

 M = Sum(j=0,i^2,j) = ((i^2+1)*(i^2))/2 = (i^4 + i^2)/2

 N = Sum(i=0, n, M) = 1/2 * ( Sum(i=0, n, (i^4)) + Sum(i=0, n, (i^2)) )

Ambas son fórmulas bien conocidas y, después de jugar un poco, obtienes:

 N = (n^5)/10 + (n^4)/4 + (n^3)/3 + (n^2)/4 + n/15

Este debería ser el número exacto de pasos que toma el ciclo, pero si está interesado en la notación O, puede notar que n ^ 5 es la parte de crecimiento más fuerte, por lo que la solución es O (n ^ 5)

Respondido 05 Feb 12, 16:02

Si procede metódicamente con la notación Sigma, obtendrá el siguiente resultado:

enter image description here

contestado el 05 de mayo de 14 a las 02:05

Intente contar cuántas veces se ejecuta el ciclo interno:

El bucle medio corre

0*0 times when i == 0
1*1 times when i == 1
2*2 times when i == 2
...
n*n = n^2 times when i == n.

Así es O(n^2).

Respondido 05 Feb 12, 05:02

Es O (n ^ 2) en la última ejecución. Es mucho más que eso terminado todos carreras. - nick barnes

Sí. Lo que quise decir es la complejidad de SOLO el ciclo medio es O(n^2). - Latif sufí

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.