Buscar..


Información básica del algoritmo de subarray máximo

El problema de subarray máximo es el método para encontrar el subarray contiguo dentro de una matriz unidimensional de números que tiene la suma más grande.

El problema fue propuesto originalmente por Ulf Grenander de la Brown University en 1977, como un modelo simplificado para la estimación de máxima probabilidad de patrones en imágenes digitalizadas.

Podemos resolver este problema, consideremos una lista de varios enteros. Podríamos estar interesados ​​en cuál subconjunto completamente adyacente tendrá la mayor suma. Por ejemplo, si tenemos la matriz [0, 1, 2, -2, 3, 2] , el subarreglo máximo es [3, 2] , con una suma de 5 .

Enfoque de fuerza bruta para la solución:

Este método es el más ineficiente para encontrar la solución. En esto, terminaremos repasando cada posible subarreglo, y luego encontraremos la suma de todos ellos. Por fin, compare todos los valores y averigüe el subarray máximo.

Pseudo código para el enfoque de fuerza bruta:

MaxSubarray(array)
  maximum = 0
  for i in input
    current = 0
    for j in input
       current += array[j]
       if current > maximum
         maximum = current
  return maximum

La complejidad del tiempo para el método de fuerza bruta es O(n^2) . Así que vamos a pasar a dividir y conquistar el enfoque.

Divide y conquista el enfoque para la solución:

Encuentra la suma de los subarrays en el lado izquierdo, los subarrays en el lado derecho. Luego, eche un vistazo a todos los que cruzan la división del centro y finalmente devuelva la suma máxima. Debido a que este es un algoritmo de dividir y conquistar, necesitamos tener dos funciones diferentes.

Lo primero es dividir paso,

maxSubarray(array)
  if start = end
    return array[start]
  else
    middle = (start + end) / 2
    return max(maxSubarray(array(From start to middle)), maxSubarray(array(From middle + 1 to end)), maxCrossover(array))

En la segunda parte, separe las diferentes partes que se crean en la primera parte.

maxCrossover(array)
  currentLeftSum = 0
      leftSum = 0
  currentRightSum = 0
      rightSum = 0
  for i in array
    currentLeftSum += array[i]
    if currentLeftSum > leftSum
      leftSum = currentLeftSum
  for i in array
    currentRightSum += array[i]
    if currentRightSum > rightSum
      rightSum = currentRightSum
  return leftSum + rightSum

La complejidad del tiempo para el método de Dividir y Conquistar es O(nlogn) . Así que vamos a pasar al enfoque de la programación dinámica.

Enfoque de programación dinámica:

Esta solución también se conoce como algoritmo de Kadane. Es un algoritmo de tiempo lineal. Esta solución es dada por Joseph B. Kadane a finales de los 70.

Este algoritmo solo pasa por el bucle, cambiando continuamente la suma máxima actual. Curiosamente, este es un ejemplo muy simple de un algoritmo de programación dinámico, ya que toma un problema de superposición y lo reduce para que podamos encontrar una solución más eficiente.

Pseudo código del algoritmo de Kadane:

MaxSubArray(array)
  max = 0
  currentMax = 0
  for i in array
    currentMax += array[i]
    if currentMax < 0
      currentMax = 0
    if max < currentMax
      max = currentMax
  return max

La complejidad del tiempo para el algoritmo de Kadane es O(n) .

Implementación de C #

public class MaximumSubarray
{
    private static int Max(int a, int b)
    {
        return a > b ? a : b;
    }

    static int MaxSubArray(int[] input, int n)
    {
        int max = input[0];
        int currentMax = input[0];
        for (int i = 1; i < n; i++)
        {
            currentMax = Max(input[i], currentMax + input[i]);
            max = Max(max, currentMax);
        }
        return max;
    }

    public static int Main(int[] input)
    {
        int n = input.Length;
        return MaxSubArray(input, n);
    }
}


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow