Time Complexity
Time Complexity o tiempo de ejecución es una medida de la cantidad de tiempo que un algoritmo necesita para ejecutarse. No se mide en segundos, sino en operaciones. Dicho de otra forma, es el saber cuántas operaciones primitivas son ejecutadas.
Cuando hablamos de time complexity, no pensamos en todos los pequeños detalles, sino que (generalmente) solamente queremos tener una estimación big picture
, por lo tanto eliminamos o no obtenemos lo que se llama non-significant numbers
, que es cualquier cosa que no es O(logn), O(n), O(n^2), O(k^n)
.
Si el data set es pequeño, es mejor centrarse en la legibilidad del código en lugar del performance
Quadratic time (n^2)
Un ejemplo es cuando cada número es comparado con todos los otros, usando nested loops.
n | 3 | 5 | 10 | 100 |
---|---|---|---|---|
Ops | 9 | 25 | 100 | 1000 |
Conforme nuestros datos crecen, el número de operaciones aumentan a la potencia de 2 (n^2).
Este es un ejemplo de Time Complexity.
Linear time (n)
Ejemplo: cuando queremos obtener el valor mínimo y máximo de un array, usando dos loops, pero no anidados.
100 | 20 | 50 | 200 | … | 30 | |
---|---|---|---|---|---|---|
Min | 100 | 20 | 20 | 20 | … | 20 |
Max | 100 | 100 | 100 | 200 | … | 200 |
¿Cuántas comparaciones se hacen?
Para el primer loop, se hacen n comparaciones, donde n es el tamaño del array. Para el segundo loop, también se hacen n comparaciones.
Entonces, la complejidad de nuestro algoritmo es 2n (hay que recordar que nuestros loops no estaban anidados).
Conforme nuestros datos crecen, el número de operaciones aumentan a por 2.
Constant time (1)
Imaginemos que tenemos un array de números, este array ya está ordenado, y queremos obtener el valor mínimo y máximo.
¿Cuántas comparaciones se hacen?
Para obtener el valor mínimo, solo necesitamos obtener el primer valor, lo que sería una operación.
Para obtener el valor máximo, solo necesitamos obtener el ultimo valor, lo que sería una operación.
Esto nos deja una complejidad de 2.
Nombre Big-O | # de operaciones | Algoritmo |
---|---|---|
O(n^2), quadratic | n^2 | Comparar todos los números |
O(n), linear | 2n | Obtener el mínimo y el máximo |
O(1), constant | 2 | En un array que ya está ordenado, obtener el mínimo y el máximo |
Logarithmic time (log n)
Conforme nuestros datos crecen, el número de operaciones que se requiere hacer, disminuye por una fracción.
Un ejemplo de esto es cuando se hace un loop sobre un array, y cada vez que se hace el loop, cortas el problema a la mitad (o alguna fracción. Base 2 divida por 2, base 3 dividida por 3…).
Big-O Notation de más rápido a más lento
Nombre | constant | logarithmic | linear | quadratic | exponential |
---|---|---|---|---|---|
Notación | O(1) | O(logn) | O(n) | O(n^2) | O(k^n) |
Complejidad de expresiones comunes
Complejidad | Operación |
---|---|
O(1) | Ejecutando una declaración |
O(1) | Búsqueda de un valor en un array, objeto, variable |
O(logn) | Loop que corta el problema a la mitad en cada iteración |
O(n) | Recorrer los valores de una matriz (for/map/forEach/…) |
O(n^2) | Dos loops anidados |
O(n^3) | Tres loops anidados |
Métodos y expresiones de JS
|
|
.shift
es linear porque hay que mover todos los elementos una posición a la izquierda.
.forEach
y .map
son métodos solo loops, el problema viene en el callback, este puede elevar la complejidad del algoritmo.
Ejemplo
|
|
Space Complexity
Space Complexity es una medida de la cantidad de espacio que un algoritmo usa.
Si el algoritmo copia un array cierta cantidad de veces, entonces en memoria tienes cierta cantidad de arrays, entonces tienes cierta cantidad de space complexity.
Funciona con las mismas medidas que time complexity, pero en lugar del número de operaciones, pensamos en la cantidad de espacio que usa el algoritmo.