Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

202
Vistas
Suma máxima de rutas de 2 listas

Mi pregunta es sobre este kata en Codewars. La función toma dos listas ordenadas con elementos distintos como argumentos. Estas listas pueden o no tener elementos comunes. La tarea es encontrar la suma máxima de rutas. Mientras encuentra la suma, si hay elementos comunes, puede elegir cambiar su ruta a la otra lista.

El ejemplo dado es así:

 list1 = [0, 2, 3, 7, 10, 12] list2 = [1, 5, 7, 8] 0->2->3->7->10->12 => 34 0->2->3->7->8 => 20 1->5->7->8 => 21 1->5->7->10->12 => 35 (maximum path)

Resolví el kata pero mi código no coincide con los criterios de rendimiento, por lo que se agotó el tiempo de ejecución. ¿Qué puedo hacer por eso?

Aquí está mi solución:

 def max_sum_path(l1:list, l2:list): common_items = list(set(l1).intersection(l2)) if not common_items: return max(sum(l1), sum(l2)) common_items.sort() s = 0 new_start1 = 0 new_start2 = 0 s1 = 0 s2 = 0 for item in common_items: s1 = sum(itertools.islice(l1, new_start1, l1.index(item))) s2 = sum(itertools.islice(l2, new_start2, l2.index(item))) new_start1 = l1.index(item) new_start2 = l2.index(item) s += max(s1, s2) s1 = sum(itertools.islice(l1, new_start1, len(l1))) s2 = sum(itertools.islice(l2, new_start2, len(l2))) s += max(s1, s2) return s
over 4 years ago · Santiago Trujillo
4 Respuestas
Responde la pregunta

0

Una vez que conozca los elementos compartidos entre las dos listas, puede iterar sobre cada lista por separado para resumir los elementos entre los elementos compartidos, construyendo así una lista de sumas parciales. Estas listas tendrán la misma longitud para ambas listas de entrada, porque el número de elementos compartidos es el mismo.

La suma máxima de la ruta se puede encontrar tomando el máximo entre las dos listas para cada tramo entre valores compartidos:

 def max_sum_path(l1, l2): shared_items = set(l1) & set(l2) def partial_sums(lst): result = [] partial_sum = 0 for item in lst: partial_sum += item if item in shared_items: result.append(partial_sum) partial_sum = 0 result.append(partial_sum) return result return sum(map(max, partial_sums(l1), partial_sums(l2)))

Complejidad temporal: solo iteramos una vez sobre cada lista (la iteración sobre las listas más cortas de sumas parciales es irrelevante aquí), por lo que este código es lineal en la longitud de las listas de entrada. Sin embargo, como usted y Kelly Bundy han notado, su propio algoritmo en realidad tiene la misma complejidad de tiempo, excepto por la parte de clasificación de elementos comunes, que no parece ser demasiado relevante para los casos de prueba dados.

Entonces, como conclusión general, si su objetivo es solo hacer que su código sea lo suficientemente rápido para pasar ciertos casos de prueba, puede ser mejor perfilar la ejecución para encontrar los sumideros de tiempo en la implementación real en lugar de preocuparse por los peores escenarios teóricos.

over 4 years ago · Santiago Trujillo Denunciar

0

Su algoritmo es realmente rápido, solo que su implementación es lenta.

Las dos cosas que hacen que tome el tiempo total O(n²):

  • l1.index(item) siempre busca desde el principio de la lista. Debería ser l1.index(item, new_start1) .
  • itertools.islice(l1, new_start1, ...) crea un iterador para l1 e itera sobre los primeros elementos new_start1 antes de llegar a los elementos que desea. Así que solo usa un segmento de lista normal en su lugar.

Entonces es solo O (n log n) para la clasificación y O (n) para todo lo demás. Y la clasificación O (n log n) es rápida, fácilmente podría tomar menos tiempo que la parte O (n) para cualquier entrada permitida e incluso más grandes.

Aquí está la versión reescrita, se acepta en aproximadamente 6 segundos, al igual que las soluciones de las otras respuestas.

 def max_sum_path(l1:list, l2:list): common_items = list(set(l1).intersection(l2)) if not common_items: return max(sum(l1), sum(l2)) common_items.sort() s = 0 new_start1 = 0 new_start2 = 0 s1 = 0 s2 = 0 for item in common_items: next_start1 = l1.index(item, new_start1) # changed next_start2 = l2.index(item, new_start2) # changed s1 = sum(l1[new_start1 : next_start1]) # changed s2 = sum(l2[new_start2 : next_start2]) # changed new_start1 = next_start1 # changed new_start2 = next_start2 # changed s += max(s1, s2) s1 = sum(l1[new_start1:]) # changed s2 = sum(l2[new_start2:]) # changed s += max(s1, s2) return s

O podría usar iteradores en lugar de índices. Aquí está su solución reescrita para hacer eso, también se acepta en aproximadamente 6 segundos:

 def max_sum_path(l1:list, l2:list): common_items = sorted(set(l1) & set(l2)) s = 0 it1 = iter(l1) it2 = iter(l2) for item in common_items: s1 = sum(iter(it1.__next__, item)) s2 = sum(iter(it2.__next__, item)) s += max(s1, s2) + item s1 = sum(it1) s2 = sum(it2) s += max(s1, s2) return s

Combinaría las últimas cuatro líneas en una, simplemente lo dejaría como lo tenía para que sea más fácil de comparar.

over 4 years ago · Santiago Trujillo Denunciar

0

Esto se puede hacer en un solo paso en el tiempo de ejecución O(n) y la complejidad del espacio O(1) . Todo lo que necesita son dos punteros para atravesar ambas matrices en paralelo y dos valores de ruta.

Incrementa el puntero al elemento más pequeño y agrega su valor a su ruta. Cuando encuentra un elemento común, lo agrega a ambas rutas y luego establece ambas rutas al valor máximo.

 def max_sum_path(l1, l2): path1 = 0 path2 = 0 i = 0 j = 0 while i < len(l1) and j < len(l2): if l1[i] < l2[j]: path1 += l1[i] i += 1 elif l2[j] < l1[i]: path2 += l2[j] j += 1 else: # Same element in both paths path1 += l1[i] path2 += l1[i] path1 = max(path1, path2) path2 = path1 i += 1 j += 1 while i < len(l1): path1 += l1[i] i += 1 while j < len(l2): path2 += l2[j] j += 1 return max(path1, path2)
over 4 years ago · Santiago Trujillo Denunciar

0

Puntos de referencia

En la pestaña Discurso , puede hacer clic en "Mostrar casos de prueba de Kata" (una vez que resolvió el kata) para ver su generador de casos de prueba. Lo usé para comparar las soluciones publicadas hasta ahora, así como una mía. Unas pocas docenas de rondas, ya que los casos de prueba son bastante aleatorios, lo que provoca una gran fluctuación en el tiempo de ejecución. En cada ronda, todos los casos de prueba generados se entregaron a todas las soluciones (por lo que en cada ronda, todas las soluciones obtuvieron los mismos casos de prueba).

Casos de prueba de Codewars

Y también el peor caso de Kelly Bundy para clasificar el conjunto de valores comunes:

ingrese la descripción de la imagen aquí

Seguirá el código.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda