Cómo encontrar la complejidad temporal de un algoritmo

890

La pregunta

¿Cómo encontrar la complejidad temporal de un algoritmo?

¿Qué he hecho antes de publicar una pregunta en SO?

He pasado por esto , este y muchos otros enlaces

Pero en ningún lugar pude encontrar una explicación clara y directa sobre cómo calcular la complejidad del tiempo.

Que sé yo ?

Digamos para un código tan simple como el siguiente:

char h = 'y'; // This will be executed 1 time
int abc = 0; // This will be executed 1 time

Digamos para un bucle como el siguiente:

for (int i = 0; i < N; i++) {        
    Console.Write('Hello World !');
}

int i = 0; Esto se ejecutará solo una vez . El tiempo se calcula realmente i=0y no la declaración.

i <N; Esto se ejecutará N + 1 veces

i ++; Esto se ejecutará N veces

Entonces, el número de operaciones requeridas por este ciclo es

{1+ (N + 1) + N} = 2N + 2

Nota: Esto aún puede estar mal, ya que no estoy seguro de mi comprensión sobre el cálculo de la complejidad del tiempo

Qué quiero saber ?

Ok, entonces estos pequeños cálculos básicos creo que los sé, pero en la mayoría de los casos he visto la complejidad del tiempo como

O (N), O (n2), O (log n), O (n!) .... y muchos otros ,

¿Alguien puede ayudarme a entender cómo se calcula la complejidad temporal de un algoritmo? Estoy seguro de que hay muchos novatos como yo que quieren saber esto.

Yasser Shaikh
fuente
138
Bono para aquellos interesados: The Big O Cheat Sheet bigocheatsheet.com
msanford
44
Mira este blog: mohalgorithmsorbit.blogspot.com . Cubre algoritmos recursivos y (especialmente) iterativos.
Mohamed Ennahdi El Idrissi
1
¿Por qué es Console.Write ('Hello World!'); No es una máquina de instrucciones?
Chetan
Relacionado / tal vez duplicado: Big O, ¿cómo se calcula / aproxima?
Bernhard Barker
1
@Chetan Si quiere decir que debe considerar Console.Writeal calcular la complejidad, eso es cierto, pero también algo irrelevante en este caso, ya que eso solo cambia un factor constante, que big-O ignora (vea las respuestas), por lo que el resultado final sigue siendo una complejidad de O (N).
Bernhard Barker

Respuestas:

394

Cómo encontrar la complejidad temporal de un algoritmo

Suma cuántas instrucciones de máquina ejecutará en función del tamaño de su entrada y luego simplifica la expresión al término más grande (cuando N es muy grande) y puede incluir cualquier factor constante de simplificación.

Por ejemplo, veamos cómo simplificamos 2N + 2las instrucciones de la máquina para describir esto como justo O(N).

¿Por qué eliminamos los dos 2s?

Estamos interesados ​​en el rendimiento del algoritmo a medida que N se hace grande.

Considere los dos términos 2N y 2.

¿Cuál es la influencia relativa de estos dos términos cuando N se hace grande? Supongamos que N es un millón.

Entonces, el primer término es de 2 millones y el segundo es de solo 2.

Por esta razón, eliminamos todos los términos, excepto los más grandes, para N. grande

Entonces, ahora hemos pasado de 2N + 2a 2N.

Tradicionalmente, solo estamos interesados ​​en el rendimiento hasta factores constantes .

Esto significa que realmente no nos importa si hay algún múltiplo constante de diferencia en el rendimiento cuando N es grande. La unidad de 2N no está bien definida en primer lugar de todos modos. Entonces podemos multiplicar o dividir por un factor constante para llegar a la expresión más simple.

Entonces se 2Nvuelve justo N.

Andrew Tomazos
fuente
53
oye, gracias por hacerme saber "por qué O (2N + 2) a O (N)" muy bien explicado, pero esto era solo una parte de la pregunta más importante, quería que alguien señalara algún enlace a un recurso oculto o en en general, quería saber cómo terminar con complejidades de tiempo como O (N), O (n2), O (log n), O (n!), etc. Sé que puedo preguntar mucho, pero todavía puedo intentarlo: {)
Yasser Shaikh
3
Bueno, la complejidad entre paréntesis es cuánto tiempo lleva el algoritmo, simplificado usando el método que he explicado. Calculamos cuánto tiempo tarda el algoritmo simplemente sumando la cantidad de instrucciones de máquina que ejecutará. Podemos simplificar solo observando los bucles más ocupados y dividiéndolos por factores constantes como he explicado.
Andrew Tomazos
44
Dar un ejemplo de respuesta hubiera sido de gran ayuda para futuros lectores. Simplemente entregar un enlace para el que tengo que registrarme, realmente no me ayuda cuando solo quiero leer un texto bien explicado.
bad_keypoints
2
Sugeriría ver los videos del Dr. Naveen Garg (IIT Delhi Prof.) si desea obtener buenos conocimientos sobre DS y la complejidad del tiempo. Consulte el enlace. nptel.ac.in/courses/106102064
Rohit Bandil
2
(cont.) Esta jerarquía tendría una altura en el orden de log N. En cuanto a O (N!) mis analogías probablemente no lo cortarán, pero las permutaciones están en ese orden: es prohibitivamente empinada, más que cualquier polinomio o exponencial. ¡Hay exactamente 10! segundos en seis semanas pero el universo es menos de 20! segundos de edad
John P
389

Este es un excelente artículo: http://www.daniweb.com/software-development/computer-science/threads/13488/time-complexity-of-algorithm

La respuesta a continuación se copia desde arriba (en caso de que el enlace excelente se rompa)

La métrica más común para calcular la complejidad del tiempo es la notación Big O. Esto elimina todos los factores constantes para que el tiempo de ejecución pueda estimarse en relación con N a medida que N se aproxima al infinito. En general, puedes pensarlo así:

statement;

Es constante El tiempo de ejecución de la declaración no cambiará en relación con N.

for ( i = 0; i < N; i++ )
     statement;

Es lineal. El tiempo de ejecución del ciclo es directamente proporcional a N. Cuando N se duplica, también lo hace el tiempo de ejecución.

for ( i = 0; i < N; i++ ) {
  for ( j = 0; j < N; j++ )
    statement;
}

Es cuadrático El tiempo de ejecución de los dos bucles es proporcional al cuadrado de N. Cuando N se duplica, el tiempo de ejecución aumenta en N * N.

while ( low <= high ) {
  mid = ( low + high ) / 2;
  if ( target < list[mid] )
    high = mid - 1;
  else if ( target > list[mid] )
    low = mid + 1;
  else break;
}

Es logarítmico El tiempo de ejecución del algoritmo es proporcional al número de veces que N puede dividirse entre 2. Esto se debe a que el algoritmo divide el área de trabajo por la mitad con cada iteración.

void quicksort ( int list[], int left, int right )
{
  int pivot = partition ( list, left, right );
  quicksort ( list, left, pivot - 1 );
  quicksort ( list, pivot + 1, right );
}

Es N * log (N). El tiempo de ejecución consta de N bucles (iterativos o recursivos) que son logarítmicos, por lo que el algoritmo es una combinación de lineal y logarítmico.

En general, hacer algo con cada elemento en una dimensión es lineal, hacer algo con cada elemento en dos dimensiones es cuadrático, y dividir el área de trabajo por la mitad es logarítmico. Existen otras medidas de Big O como la raíz cúbica, exponencial y cuadrada, pero no son tan comunes. La notación O grande se describe como O ( <type> )dónde <type>está la medida. El algoritmo de clasificación rápida se describiría como O ( N * log ( N ) ).

Tenga en cuenta que nada de esto ha tenido en cuenta las mejores, medias y peores medidas. Cada uno tendría su propia notación Big O. También tenga en cuenta que esta es una explicación MUY simplista. Big O es el más común, pero también es más complejo de lo que he mostrado. También hay otras anotaciones como omega grande, o pequeña y theta grande. Probablemente no los encontrará fuera de un curso de análisis de algoritmos. ;)

Achow
fuente
10
El algoritmo de clasificación rápida en el peor de los casos tiene un tiempo de ejecución de N ^ 2, aunque este comportamiento es raro.
nbro
2
IIRC, little omega y omega grande se utilizan para la complejidad de los casos mejor y promedio (siendo Big O el peor de los casos), de modo que "las mejores, las medias y las peores medidas de caso. Cada uno tendría su propia notación Big O". Sería incorrecto. Incluso hay más símbolos con significados más específicos, y CS no siempre usa el símbolo más apropiado. Llegué a aprender todo esto por el nombre de los símbolos de Landau por cierto. +1 de todos modos b / c mejor respuesta.
hiergiltdiestfu
@hiergiltdiestfu Big-O, Big-Omega, etc. se pueden aplicar a cualquiera de los mejores, promedio o peores tiempos de ejecución de un algoritmo. ¿Cómo se relacionan O y Ω con el peor y el mejor caso?
Bernhard Barker
Además, si alguien está buscando cómo calcular O grande para cualquier método: stackoverflow.com/a/60354355/4260691
OhadM
Una de las mejores explicaciones.
Shivaraj Patil
172

Tomado de aquí: Introducción a la complejidad temporal de un algoritmo

1. Introducción

En informática, la complejidad temporal de un algoritmo cuantifica la cantidad de tiempo que tarda un algoritmo en ejecutarse en función de la longitud de la cadena que representa la entrada.

2. Gran notación O

La complejidad de tiempo de un algoritmo se expresa comúnmente usando una notación O grande, que excluye coeficientes y términos de orden inferior. Cuando se expresa de esta manera, se dice que la complejidad del tiempo se describe asintóticamente, es decir, a medida que el tamaño de entrada llega al infinito.

Por ejemplo, si el tiempo requerido por un algoritmo en todas las entradas de tamaño n es como máximo 5n 3 + 3n, la complejidad del tiempo asintótico es O (n 3 ). Más sobre eso más tarde.

Pocos ejemplos más:

  • 1 = O (n)
  • n = O (n 2 )
  • log (n) = O (n)
  • 2 n + 1 = O (n)

3. O (1) Tiempo constante:

Se dice que un algoritmo se ejecuta en tiempo constante si requiere la misma cantidad de tiempo, independientemente del tamaño de entrada.

Ejemplos:

  • matriz: acceder a cualquier elemento
  • pila de tamaño fijo: métodos push y pop
  • cola de tamaño fijo: métodos en cola y en cola

4. O (n) Tiempo lineal

Se dice que un algoritmo se ejecuta en tiempo lineal si su ejecución de tiempo es directamente proporcional al tamaño de entrada, es decir, el tiempo crece linealmente a medida que aumenta el tamaño de entrada.

Considere los siguientes ejemplos, a continuación estoy buscando linealmente un elemento, esto tiene una complejidad temporal de O (n).

int find = 66;
var numbers = new int[] { 33, 435, 36, 37, 43, 45, 66, 656, 2232 };
for (int i = 0; i < numbers.Length - 1; i++)
{
    if(find == numbers[i])
    {
        return;
    }
}

Más ejemplos:

  • Matriz: búsqueda lineal, recorrido, búsqueda mínima, etc.
  • ArrayList: contiene el método
  • Cola: contiene el método

5. O (log n) Tiempo logarítmico:

Se dice que un algoritmo se ejecuta en tiempo logarítmico si su ejecución de tiempo es proporcional al logaritmo del tamaño de entrada.

Ejemplo: búsqueda binaria

Recuerde el juego de las "veinte preguntas": la tarea es adivinar el valor de un número oculto en un intervalo. Cada vez que hace una suposición, le dicen si su suposición es demasiado alta o demasiado baja. El juego de veinte preguntas implica una estrategia que utiliza su número de conjetura para reducir a la mitad el tamaño del intervalo. Este es un ejemplo del método general de resolución de problemas conocido como búsqueda binaria.

6. O (n 2 ) Tiempo cuadrático

Se dice que un algoritmo se ejecuta en tiempo cuadrático si su ejecución de tiempo es proporcional al cuadrado del tamaño de entrada.

Ejemplos:

7. Algunos enlaces útiles

Yasser Shaikh
fuente
17
Nota: el primer enlace está roto.
Ziezi
2
O (n2) debe escribirse O (n ^ 2) para evitar confusiones.
Rizki Hadiaturrasyid
100

Aunque hay algunas buenas respuestas para esta pregunta. Me gustaría dar otra respuesta aquí con varios ejemplos de loop.

  • O (n) : la complejidad temporal de un bucle se considera como O (n) si las variables del bucle se incrementan / disminuyen en una cantidad constante. Por ejemplo, las siguientes funciones tienen una complejidad de tiempo O (n) .

    // Here c is a positive integer constant   
    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 ^ c) : la complejidad temporal de los bucles anidados es igual al número de veces que se ejecuta la instrucción más interna. Por ejemplo, los siguientes bucles de muestra tienen una complejidad de tiempo O (n ^ 2)

    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
    }
    

    Por ejemplo, el orden de selección y el orden de inserción tienen una complejidad de tiempo O (n ^ 2) .

  • O (Logn) La complejidad del tiempo de un ciclo se considera como O (Logn) si las variables del ciclo se dividen / multiplican por una cantidad constante.

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

    Por ejemplo, la búsqueda binaria tiene una complejidad de tiempo O (Logn) .

  • O (LogLogn) La complejidad del tiempo de un ciclo se considera como O (LogLogn) si las variables del ciclo se reducen / aumentan exponencialmente en una cantidad constante.

    // Here c is a constant greater than 1   
    for (int i = 2; i <=n; i = pow(i, c)) { 
       // some O(1) expressions
    }
    //Here fun is sqrt or cuberoot or any other constant root
    for (int i = n; i > 0; i = fun(i)) { 
       // some O(1) expressions
    }
    

Un ejemplo de análisis de complejidad temporal.

int fun(int n)
{    
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j < n; j += i)
        {
            // Some O(1) task
        }
    }    
}

Análisis :

For i = 1, the inner loop is executed n times. For i = 2, the inner loop is executed approximately n/2 times. For i = 3, the inner loop is executed approximately n/3 times. For i = 4, the inner loop is executed approximately n/4 times. ……………………………………………………. For i = n, the inner loop is executed approximately n/n times.

Entonces, la complejidad de tiempo total del algoritmo anterior es (n + n/2 + n/3 + … + n/n), que se convierte enn * (1/1 + 1/2 + 1/3 + … + 1/n)

Lo importante de las series (1/1 + 1/2 + 1/3 + … + 1/n)es igual a O (Logn) . Entonces, la complejidad temporal del código anterior es O (nLogn) .


Ref: 1 2 3

zangw
fuente
1
@ Simon, ¿podría averiguar qué parte es incorrecta?
zangw
gracias por preguntar. Leí mal el código. Eliminé mi comentario. ¡Lo siento!
Simon
74

Complejidad del tiempo con ejemplos

1 - Operaciones básicas (aritmética, comparaciones, acceso a elementos de la matriz, asignación): el tiempo de ejecución siempre es constante O (1)

Ejemplo:

read(x)                               // O(1)
a = 10;                               // O(1)
a = 1.000.000.000.000.000.000         // O(1)

2 - Si la declaración de lo contrario: solo toma el tiempo de ejecución máximo de dos o más declaraciones posibles.

Ejemplo:

age = read(x)                               // (1+1) = 2
if age < 17 then begin                      // 1
      status = "Not allowed!";              // 1
end else begin
      status = "Welcome! Please come in";   // 1
      visitors = visitors + 1;              // 1+1 = 2
end;

Entonces, la complejidad del pseudocódigo anterior es T (n) = 2 + 1 + max (1, 1 + 2) = 6. Por lo tanto, su gran oh sigue siendo constante T (n) = O (1).

3 - Bucle (para, mientras, repetir): el tiempo de ejecución de esta instrucción es el número de bucles multiplicado por el número de operaciones dentro de ese bucle.

Ejemplo:

total = 0;                                  // 1
for i = 1 to n do begin                     // (1+1)*n = 2n
      total = total + i;                    // (1+1)*n = 2n
end;
writeln(total);                             // 1

Entonces, su complejidad es T (n) = 1 + 4n + 1 = 4n + 2. Por lo tanto, T (n) = O (n).

4 - Bucle anidado (bucle dentro de bucle): dado que hay al menos un bucle dentro del bucle principal, el tiempo de ejecución de esta instrucción utilizó O (n ^ 2) u O (n ^ 3).

Ejemplo:

for i = 1 to n do begin                     // (1+1)*n  = 2n
   for j = 1 to n do begin                  // (1+1)n*n = 2n^2
       x = x + 1;                           // (1+1)n*n = 2n^2
       print(x);                            // (n*n)    = n^2
   end;
end;

Tiempo de funcionamiento común

Existen algunos tiempos de ejecución comunes al analizar un algoritmo:

  1. O (1) - Tiempo constante El tiempo constante significa que el tiempo de ejecución es constante, no se ve afectado por el tamaño de entrada .

  2. O (n) - Tiempo lineal Cuando un algoritmo acepta n tamaño de entrada, también realizaría n operaciones.

  3. O (log n) - Algoritmo de tiempo logarítmico que tiene tiempo de ejecución O (log n) es un poco más rápido que O (n). Comúnmente, el algoritmo divide el problema en subproblemas con el mismo tamaño. Ejemplo: algoritmo de búsqueda binaria, algoritmo de conversión binaria.

  4. O (n log n) - Tiempo lineal lineal Este tiempo de ejecución se encuentra a menudo en "algoritmos de división y conquista" que dividen el problema en subproblemas de forma recursiva y luego los fusionan en n tiempo. Ejemplo: algoritmo Merge Sort.

  5. O (n 2 ) - ¡Algoritmo de clasificación de burbujas de aspecto de tiempo cuadrático!

  6. O (n 3 ) - Tiempo cúbico Tiene el mismo principio con O (n 2 ).

  7. O (2 n ) - Tiempo exponencial Es muy lento a medida que la entrada aumenta, si n = 1000,000, T (n) sería 21000,000. El algoritmo de fuerza bruta tiene este tiempo de ejecución.

  8. O (n!) - Tiempo factorial ¡¡¡LO MÁS LENTO !!! Ejemplo: Problema de vendedor de viajes (TSP)

Tomado de este artículo . Muy bien explicado debería dar una lectura.

Yasser Shaikh
fuente
En tu segundo ejemplo, escribiste visitors = visitors + 1es 1 + 1 = 2. ¿Podrías explicarme por qué hiciste eso?
Sajib Acharya
3
@Sajib Acharya Míralo de derecha a izquierda. Primer paso: calcular visitors + 1 Segundo paso: asignar valor desde el primer paso a visitors So, la expresión anterior está formada por dos declaraciones; primer paso + segundo paso => ​​1 + 1 = 2
Bozidar Sikanjic
@nbro Por qué es 1 + 1 enage = read(x) // (1+1) = 2
Humty
@BozidarSikanjic Por qué es 1 + 1 enage = read(x) // (1+1) = 2
Humty
1
@Humty Verifique el comienzo de esta respuesta: read(x) // O(1) a = 10; // O(1)Primero es la función call => O (1) ///// Segundo es la asignación, como dijo nbro, pero 10 es constante, entonces el segundo es => O (1) ...
Bozidar Sikanjic
41

Cuando analiza el código, debe analizarlo línea por línea, contando cada operación / reconociendo la complejidad del tiempo, al final, debe sumarlo para obtener una imagen completa.

Por ejemplo, puede tener un bucle simple con complejidad lineal , pero más adelante en ese mismo programa puede tener un bucle triple que tiene complejidad cúbica , por lo que su programa tendrá complejidad cúbica . El orden de crecimiento de las funciones entra en juego aquí.

Veamos cuáles son las posibilidades de complejidad de tiempo de un algoritmo, puede ver el orden de crecimiento que mencioné anteriormente:

  • Constante de tiempo tiene un orden de crecimiento1, por ejemplo:a = b + c.

  • El tiempo logarítmico tiene un orden de crecimientoLogN, generalmente ocurre cuando se divide algo por la mitad (búsqueda binaria, árboles, incluso bucles) o cuando se multiplica algo de la misma manera.

  • Lineal , el orden de crecimiento esN, por ejemplo

    int p = 0;
    for (int i = 1; i < N; i++)
      p = p + 2;
    
  • El orden de crecimiento lineal esn*logN, generalmente, ocurre en algoritmos de división y conquista.

  • ElN^3 ejemplo clásicode orden de crecimiento cúbico es un ciclo triple donde se verifican todos los trillizos:

    int x = 0;
    for (int i = 0; i < N; i++)
       for (int j = 0; j < N; j++)
          for (int k = 0; k < N; k++)
              x = x + 2
    
  • El orden de crecimiento exponencial2^N generalmente ocurre cuando realiza una búsqueda exhaustiva, por ejemplo, verifica los subconjuntos de algún conjunto.

Aleksandar Makragić
fuente
Si este fuera el caso, ¿cuál sería la complejidad? for (int i = 0; i <N; i ++) for (int j = i + 1; j <N; j ++) for (int k = j + 1; k <N; k ++) x = x + 2
usuario3156040
35

Hablando en términos generales, la complejidad del tiempo es una forma de resumir cómo crece el número de operaciones o el tiempo de ejecución de un algoritmo a medida que aumenta el tamaño de entrada.

Como la mayoría de las cosas en la vida, un cóctel puede ayudarnos a entender.

EN)

Cuando llegas a la fiesta, tienes que estrechar la mano de todos (hacer una operación en cada elemento). A medida que Naumenta el número de asistentes , el tiempo / trabajo que le llevará estrechar la mano de todos aumenta a medida que O(N).

¿Por qué O(N)y no cN?

Existe una variación en la cantidad de tiempo que se necesita para estrechar la mano de las personas. Podría promediar esto y capturarlo de manera constante c. Pero la operación fundamental aquí, estrechar la mano de todos, siempre sería proporcional O(N), sin importar lo que cfuera. Al debatir si deberíamos ir a una fiesta de cócteles, a menudo estamos más interesados ​​en el hecho de que tendremos que conocer a todos que en los detalles minuciosos de cómo son esas reuniones.

O (N ^ 2)

El anfitrión del cóctel quiere que juegues un juego tonto donde todos se encuentran con todos los demás. Por lo tanto, debe conocer a N-1otras personas y, debido a que la siguiente persona ya lo ha conocido, debe conocer a otras N-2personas, y así sucesivamente. La suma de esta serie es x^2/2+x/2. A medida que crece el número de asistentes, el x^2término se hace grande rápidamente , por lo que simplemente dejamos todo lo demás.

O (N ^ 3)

Debe conocer a todos los demás y, durante cada reunión, debe hablar sobre todos los demás en la sala.

O (1)

El anfitrión quiere anunciar algo. Beben una copa de vino y hablan en voz alta. Todos los oyen. Resulta que no importa cuántos asistentes haya, esta operación siempre toma la misma cantidad de tiempo.

O (log N)

El anfitrión ha colocado a todos en la mesa en orden alfabético. ¿Donde esta Dan? Usted razona que debe estar en algún lugar entre Adam y Mandy (¡ciertamente no entre Mandy y Zach!). Dado eso, ¿está entre George y Mandy? No. Debe estar entre Adam y Fred, y entre Cindy y Fred. Y así sucesivamente ... podemos localizar eficientemente a Dan mirando la mitad del conjunto y luego la mitad de ese conjunto. Finalmente, nos fijamos en los individuos O (log_2 N) .

O (N log N)

Puede encontrar dónde sentarse en la mesa utilizando el algoritmo anterior. Si un gran número de personas se acercara a la mesa, una a la vez, y todas hicieran esto, eso llevaría tiempo O (N log N) . Esto resulta ser cuánto tiempo lleva ordenar una colección de artículos cuando deben compararse.

Mejor / peor caso

Llegas a la fiesta y necesitas encontrar a Iñigo: ¿cuánto tiempo te llevará? Depende de cuando llegues. Si todo el mundo está dando vueltas, has tocado el peor de los casos: tomará O(N)tiempo. Sin embargo, si todos están sentados a la mesa, solo tomará O(log N)tiempo. O tal vez pueda aprovechar el poder de gritos de copa de vino del anfitrión y solo tomará O(1)tiempo.

Suponiendo que el anfitrión no esté disponible, podemos decir que el algoritmo de búsqueda de Íñigo tiene un límite inferior O(log N)y un límite superior O(N), según el estado de la fiesta cuando llegue.

Espacio y comunicación

Se pueden aplicar las mismas ideas para comprender cómo los algoritmos usan el espacio o la comunicación.

Knuth ha escrito un buen artículo sobre el anterior titulado "La complejidad de las canciones" .

Teorema 2: existen canciones arbitrariamente largas de complejidad O (1).

PRUEBA: (debido a Casey y la Sunshine Band). Considere las canciones Sk definidas por (15), pero con

V_k = 'That's the way,' U 'I like it, ' U
U   = 'uh huh,' 'uh huh'

para todos los k.

Ricardo
fuente
Lo has clavado. Ahora, cada vez que voy a un cóctel, inconscientemente intentaré encontrar la Complejidad del Tiempo de cualquier evento divertido. Gracias por un ejemplo tan gracioso.
Sabunkar Tejas Sahailesh
5

Sé que esta pregunta se remonta y hay algunas respuestas excelentes aquí, sin embargo, quería compartir un poco más para las personas con mentalidad matemática que tropezarán en esta publicación. El teorema de Master es otra cosa útil para saber cuando se estudia la complejidad. No lo vi mencionado en las otras respuestas.

Kasa genciana
fuente
2

O (n) es una notación O grande utilizada para escribir la complejidad del tiempo de un algoritmo. Cuando sumas el número de ejecuciones en un algoritmo obtendrás una expresión en resultado como 2N + 2, en esta expresión N es el término dominante (el término que tiene mayor efecto en la expresión si su valor aumenta o disminuye). Ahora O (N) es la complejidad del tiempo mientras N es el término dominante. Ejemplo

For i= 1 to n;
  j= 0;
while(j<=n);
  j=j+1;

aquí el número total de ejecuciones para el bucle interno es n + 1 y el número total de ejecuciones para el bucle externo es n (n + 1) / 2, por lo que el número total de ejecuciones para todo el algoritmo es n + 1 + n (n + 1/2 ) = (n ^ 2 + 3n) / 2. aquí n ^ 2 es el término dominante, por lo que la complejidad de tiempo para este algoritmo es O (n ^ 2)

ifra khan
fuente