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

106
Vistas
Eliminar repetidamente el subarreglo promedio máximo

Tengo una matriz de enteros positivos. Por ejemplo:

 [1, 7, 8, 4, 2, 1, 4]

Una "operación de reducción" encuentra el prefijo de matriz con el promedio más alto y lo elimina. Aquí, un prefijo de arreglo significa un subarreglo contiguo cuyo extremo izquierdo es el comienzo del arreglo, como [1] o [1, 7] o [1, 7, 8] arriba. Los empates se rompen tomando el prefijo más largo.

 Original array: [ 1, 7, 8, 4, 2, 1, 4] Prefix averages: [1.0, 4.0, 5.3, 5.0, 4.4, 3.8, 3.9] -> Delete [1, 7, 8], with maximum average 5.3 -> New array -> [4, 2, 1, 4]

Repetiré la operación de reducción hasta que la matriz esté vacía:

 [1, 7, 8, 4, 2, 1, 4] ^ ^ [4, 2, 1, 4] ^ ^ [2, 1, 4] ^ ^ []

Ahora, en realidad no es necesario realizar estas modificaciones de matriz; Solo estoy buscando la lista de longitudes de prefijos que se eliminarían con este proceso, por ejemplo, [3, 1, 3] arriba.

¿Cuál es un algoritmo eficiente para calcular estas longitudes de prefijo?


El enfoque ingenuo es volver a calcular todas las sumas y promedios desde cero en cada iteración para un algoritmo O(n^2) . He adjuntado el código de Python para esto a continuación. Estoy buscando alguna mejora en este enfoque, preferiblemente, cualquier solución por debajo O(n^2) , pero también sería útil un algoritmo con la misma complejidad pero mejores factores constantes.

Estas son algunas de las cosas que he intentado (sin éxito):

  1. Mantenimiento dinámico de sumas de prefijos, por ejemplo, con un árbol indexado binario . Si bien puedo actualizar fácilmente las sumas de prefijos o encontrar una suma máxima de prefijos en O(log n) , no he encontrado ninguna estructura de datos que pueda actualizar el promedio , ya que el denominador en el promedio está cambiando.
  2. Reutilizando las 'clasificaciones' anteriores de promedios de prefijos: estas clasificaciones pueden cambiar, por ejemplo, en alguna matriz, el prefijo que termina en el índice 5 puede tener un promedio mayor que el prefijo que termina en el índice 6 , pero después de eliminar los primeros 3 elementos, ahora el el prefijo que termina en el índice 2 puede tener un promedio más pequeño que el que termina en 3 .
  3. Buscando patrones en donde terminan los prefijos; por ejemplo, el elemento más a la derecha de cualquier prefijo promedio máximo es siempre un máximo local en la matriz, pero no está claro cuánto ayuda esto.

Esta es una implementación funcional de Python del método cuadrático ingenuo:

 from fractions import Fraction def find_array_reductions(nums: List[int]) -> List[int]: """Return list of lengths of max average prefix reductions.""" def max_prefix_avg(arr: List[int]) -> Tuple[float, int]: """Return value and length of max average prefix in arr.""" if len(arr) == 0: return (-math.inf, 0) best_length = 1 best_average = Fraction(0, 1) running_sum = 0 for i, x in enumerate(arr, 1): running_sum += x new_average = Fraction(running_sum, i) if new_average >= best_average: best_average = new_average best_length = i return (float(best_average), best_length) removed_lengths = [] total_removed = 0 while total_removed < len(nums): _, new_removal = max_prefix_avg(nums[total_removed:]) removed_lengths.append(new_removal) total_removed += new_removal return removed_lengths

Editar: el código publicado originalmente tenía un error raro con grandes entradas al usar math.isclose() de Python con parámetros predeterminados para la comparación de coma flotante, en lugar de la comparación de fracciones adecuada. Esto se ha corregido en el código actual. Puede encontrar un ejemplo del error en este enlace Pruébelo en línea , junto con un prólogo que explica exactamente qué causa este error, si tiene curiosidad.

over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Este problema tiene una divertida solución O(n).

Si dibuja un gráfico de suma acumulada vs índice, entonces:

El valor promedio en el subarreglo entre dos índices es la pendiente de la línea entre esos puntos en el gráfico.

El primer prefijo de promedio más alto terminará en el punto que forma el ángulo más alto desde 0. El siguiente prefijo de promedio más alto debe tener un promedio más pequeño , y terminará en el punto que forma el ángulo más alto desde el primer final. . Continuando hasta el final de la matriz, encontramos que...

Estos segmentos de promedio más alto son exactamente los segmentos en el casco convexo superior del gráfico de suma acumulativa .

Encuentre estos segmentos usando el algoritmo de cadena monótona . Dado que los puntos ya están ordenados, toma O (n) tiempo.

 # Lengths of the segments in the upper convex hull # of the cumulative sum graph def upperSumHullLengths(arr): if len(arr) < 2: if len(arr) < 1: return [] else: return [1] hull = [(0, 0),(1, arr[0])] for x in range(2, len(arr)+1): # this has x coordinate x-1 prevPoint = hull[len(hull) - 1] # next point in cumulative sum point = (x, prevPoint[1] + arr[x-1]) # remove points not on the convex hull while len(hull) >= 2: p0 = hull[len(hull)-2] dx0 = prevPoint[0] - p0[0] dy0 = prevPoint[1] - p0[1] dx1 = x - prevPoint[0] dy1 = point[1] - prevPoint[1] if dy1*dx0 < dy0*dx1: break hull.pop() prevPoint = p0 hull.append(point) return [hull[i+1][0] - hull[i][0] for i in range(0, len(hull)-1)] print(upperSumHullLengths([ 1, 7, 8, 4, 2, 1, 4]))

huellas dactilares:

 [3, 1, 3]
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