Optimización de código
📌 ¿Cómo medir la complejidad de un algoritmo?
Para analizar la eficiencia de un algoritmo, debemos contar cuántas operaciones realiza en función del tamaño de la entrada n.
Ejemplo:
- Si un algoritmo ejecuta una sola operación, su tiempo de ejecución es O(1).
- Si recorre
nelementos en un bucle, su tiempo de ejecución es O(n). - Si usa dos bucles anidados, su tiempo de ejecución es O(n²).
📌 1. Contando Operaciones Dominantes
Cuando medimos la complejidad, solo nos interesa la operación más costosa.
Ejemplo: Sumar los primeros n números.
1public class SumNumbers { 2 public static int sum(int n) { 3 int total = 0; // 1 operación 4 for (int i = 1; i <= n; i++) { // n operaciones 5 total += i; // n operaciones 6 } 7 return total; 8 } 9}
📌 Análisis:
- El bucle se ejecuta
nveces. - La operación de suma se ejecuta
nveces. - La complejidad es O(n).
📌 2. Ignorar Constantes y Términos No Dominantes
Cuando analizamos un algoritmo, ignoramos las constantes porque no afectan el crecimiento para valores grandes de n.
Ejemplo:
1public int example(int n) { 2 int x = 10; // O(1) 3 for (int i = 0; i < n; i++) { // O(n) 4 System.out.println(i); 5 } 6 return x; 7}
- La operación
int x = 10;es constante O(1). - El bucle es O(n).
- Conclusión: O(n) domina, por lo que el algoritmo es O(n).
📌 3. Casos Peor, Mejor y Promedio
El rendimiento de un algoritmo depende del caso en el que se ejecuta.
Ejemplo: Búsqueda de un número en un array.
1public class Search { 2 public static boolean find(int[] arr, int target) { 3 for (int num : arr) { 4 if (num == target) return true; // Se detiene si lo encuentra 5 } 6 return false; 7 } 8}
📌 Análisis:
- Mejor caso:
O(1)si el número está al inicio. - Peor caso:
O(n)si el número está al final o no está en el array. - Caso promedio:
O(n/2), pero ignoramos la constante1/2, por lo que sigue siendoO(n).
📌 5. Medición Práctica del Tiempo de Ejecución
Para medir el tiempo real de ejecución, usamos funciones de temporización.
1public class TimeMeasurement { 2 public static void main(String[] args) { 3 long start = System.nanoTime(); // Inicio del tiempo 4 5 int sum = 0; 6 for (int i = 0; i < 1000000; i++) { 7 sum += i; 8 } 9 10 long end = System.nanoTime(); // Fin del tiempo 11 System.out.println("Tiempo: " + (end - start) + " ns"); 12 } 13}