Tengo una lista de números (ejemplo: [-1, 1, -4, 5]
) y tengo que eliminar los números de la lista sin cambiar la suma total de la lista. Quiero eliminar los números con el mayor valor absoluto posible, sin cambiar el total, en el ejemplo que elimina [-1, -4, 5]
saldrá [1]
por lo que la suma no cambia.eliminar números de una lista sin cambiar la suma total
Escribí el enfoque ingenuo, que es encontrar todas las combinaciones posibles que no cambian el total y ver cuál elimina el mayor valor absoluto. Pero eso es realmente lento, ya que la lista real será mucho más grande que eso.
Aquí está mi código de combinaciones:
from itertools import chain, combinations
def remove(items):
all_comb = chain.from_iterable(combinations(items, n+1)
for n in xrange(len(items)))
biggest = None
biggest_sum = 0
for comb in all_comb:
if sum(comb) != 0:
continue # this comb would change total, skip
abs_sum = sum(abs(item) for item in comb)
if abs_sum > biggest_sum:
biggest = comb
biggest_sum = abs_sum
return biggest
print remove([-1, 1, -4, 5])
Se imprime corectly (-1, -4, 5)
. Sin embargo, estoy buscando alguna solución inteligente y más eficiente que el bucle sobre todas las combinaciones de elementos posibles.
¿Alguna idea?
En este caso, es un ganar si observamos que la sum es un ítem en esta lista. Si tenemos 'sum (items)' y 'abs_sum (items)', entonces es más eficiente intentar agregar a la suma usando 1, 2, 3, etc. elementos de la lista, que están comenzando desde el caso de la lista vacía en lugar de la lista completa (?) – u0b34a0f6ae
Probablemente deberías guardar 'smallest_abs_sum' en lugar de' biggest_sum'. Considere: '[1, -1,100, -100]'. – jfs
@ J.F. Sebastian: si la entrada es '[1, -1,100, -100]' debería eliminar todo ('abs_sum' de' 202') manteniendo la suma '0'. – nosklo