Saltar al contenido
Regresar

Suma Acumulativa Eficiente: Optimiza tu Código en Python

Publicado:  a las  09:02 a.m.

¿Cansado de algoritmos que te hacen esperar más que la cola del café un lunes por la mañana? ☕ Tenemos la solución.

🔮 Enunciado del Problema

Desarrollar una función max_after_operations_master(n, queries) que optimice la manipulación de arreglos y la búsqueda de máximos tras múltiples actualizaciones. 🤖

El problema consiste en inicializar un arreglo de ceros con n posiciones. Se recibe también una matriz queries de m filas y 3 columnas. Cada fila de la matriz representa una operación de suma que debe aplicarse sobre el arreglo.

La función debe realizar las operaciones de suma descritas en la matriz queries, aplicando el valor k al rango de índices especificado por a y b (ambos inclusive). Al finalizar todas las operaciones, la función debe devolver el valor máximo encontrado en el arreglo.

NOTA IMPORTANTE: La función debe estar optimizada para ejecutarse en menos de un segundo.

Ejemplo:

>>> max_after_operations_master(10, [[1, 3, 5], [2, 5, 1]])
6

Procedimiento Visual:

Considerando la matriz queries:

a   b   k
1   3   5
2   5   1
  1. Arreglo inicializado en 0 (tamaño 10): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  2. Aplicando la primera operación (fila 1): [5, 5, 5, 0, 0, 0, 0, 0, 0, 0]
  3. Aplicando la segunda operación (fila 2): [5, 6, 6, 1, 1, 0, 0, 0, 0, 0]

El máximo valor en el arreglo final es 6.

🧩 Resolución Paso a Paso

La solución se basa en la técnica de “diferencias acumulativas” para lograr una alta eficiencia. En lugar de iterar sobre cada rango y sumar el valor k, modificamos el arreglo solo en los puntos inicial y final del rango. Posteriormente, realizamos una pasada final para calcular las sumas acumulativas y encontrar el máximo.

operations = [0] * n

Inicializamos una lista operations de tamaño n con todos los elementos en cero. Esta lista actuará como nuestro lienzo donde pintaremos los efectos de cada operación.

for query in queries:
    a, b, k = query
    operations[a - 1] += k
    operations[b] -= k

Iteramos a través de la matriz queries. Para cada fila (operación), extraemos los valores a, b y k. Incrementamos el valor en la posición a - 1 (índice inicial) por k y decrementamos el valor en la posición b (justo después del índice final) por k. Este es el corazón de la optimización: en lugar de sumar k a todo el rango, marcamos el inicio y el final del incremento.

maxval = 0
itt = 0
for num in operations:
    itt += num
    if itt > maxval:
        maxval = itt

Finalmente, iteramos sobre la lista operations calculando la suma acumulativa en cada posición. Mantenemos un registro del valor máximo encontrado hasta el momento. La magia reside en que la suma acumulativa “propaga” los incrementos y decrementos, simulando el efecto de sumar k a cada rango.

Solución Completa:

def max_after_operations_master(n, queries):
	"level: master; points: 10; time: 1"
	operations = [0] * n
	for query in queries:
		a, b, k = query
		operations[a - 1] += k
		operations[b] -= k
	maxval = 0
	itt = 0
	for num in operations:
		itt += num
		if itt > maxval:
			maxval = itt
	return maxval

🧠 Conceptos Clave

El concepto central es la técnica de diferencias acumulativas. Esta técnica transforma un problema de actualización de rangos en un problema de actualización de puntos individuales, seguido de un cálculo de sumas prefijo. La clave está en entender que sumar k a un rango [a, b] es equivalente a sumar k en la posición a y restar k en la posición b+1. Esto permite evitar iterar sobre todo el rango para cada operación, reduciendo drásticamente la complejidad temporal.

La complejidad temporal del algoritmo resultante es O(m + n), donde m es el número de queries y n es el tamaño del arreglo. Esto es significativamente más eficiente que una solución ingenua que iteraría sobre cada rango para cada query, que tendría una complejidad de O(m * n * (tamaño promedio del rango)).

¿Sabías que…? La técnica de diferencias acumulativas no solo se usa en problemas de manipulación de arreglos, sino también en procesamiento de imágenes y señales para realizar operaciones de convolución de forma eficiente.

💫 Reflexiones Finales

Esta solución demuestra el poder de la optimización algorítmica. La técnica de diferencias acumulativas transforma un problema que podría ser prohibitivamente lento en una tarea eficiente.

Posibles mejoras podrían incluir la paralelización del cálculo de la suma acumulativa, especialmente en arquitecturas con múltiples núcleos. Sin embargo, para los casos de prueba típicos, la solución actual ya es lo suficientemente rápida.

Si quieres dominar estas técnicas y convertirte en un maestro de la optimización, te invito a explorar más artículos en este blog. ¡El camino del código eficiente te espera! 😉



Publicación anterior
Día del Chocolate: Calcula cuántos chocolates puedes comprar
Siguiente publicación
Números de Armstrong: ¿Qué son y cómo detectarlos en Python?