Dada una matriz, ¿qué es un algoritmo para identificar la submatriz con la suma máxima?

Resolví un tipo similar de pregunta sobre Hackerrank.
Trataré de responder todos los métodos posibles que sean posibles. El enfoque ingenuo para esta pregunta lo resuelve en tiempo O (n ^ 3). Pero al definir un mejor algoritmo, es posible resolver esto en O (n) tiempo.
Discutiré todos los enfoques posibles (del ingenuo al mejor)

  1. Algoritmo 1
    Un algoritmo sencillo para resolver el problema es recorrer todas las formas posibles de seleccionar una submatriz, calcular la suma de los números en cada submatriz y mantener la suma máxima. El siguiente código implementa este algoritmo:

    int p = 0;
    para (int a = 1; a <= n; a ++)
    {
    para (int b = a; b <= n; b ++)
    {
    int s = 0;
    para (int c = a; c <= b; c ++)
    {s + = x [c];
    }
    p = max (p, s);
    }
    }
    cout << p << "\ n";

    El código supone que los números se almacenan en una matriz x con los índices 1 … n. Las variables a y b determinan el primer y último número en la submatriz, y la suma de los números se calcula para la variable s. La variable p contiene la suma máxima encontrada durante la búsqueda. La complejidad temporal del algoritmo es O (n3), porque consta de tres bucles anidados que pasan por la entrada

  2. Algoritmo 2

    Es fácil hacer que el primer algoritmo sea más eficiente eliminando un bucle. Esto es posible calculando la suma al mismo tiempo cuando se mueve el extremo derecho de la submatriz. El resultado es el siguiente código:

    int p = 0;
    para (int a = 1; a <= n; a ++)
    {
    int s = 0; para (int b = a; b <= n; b ++)
    {s + = x [b]; p = max (p, s); }
    }
    cout << p << "\ n";

    Después de este cambio, la complejidad del tiempo es O (n2).

  3. Algoritmo 3 (solución O (n))
    Es posible resolver esto en O (n) tiempo,
    lo que significa que podemos eliminar un bucle más. La idea es calcular, para cada posición de matriz, la suma máxima de una submatriz que termina en esa posición. Después de esto, la respuesta al problema es el máximo de esas sumas. Considere el subproblema de encontrar la submatriz de suma máxima que termina en la posición k. Hay dos posibilidades:
    1. La submatriz solo contiene el elemento en la posición k.
    2. La submatriz consiste en una submatriz que termina en la posición k − 1, seguida del elemento en la posición k.

    Nuestro objetivo es encontrar un subconjunto con suma máxima, por lo que en el caso 2 el subconjunto que termina en la posición k − 1 también debe tener la suma máxima. Por lo tanto, podemos resolver el problema de manera eficiente cuando calculamos la suma máxima de subarreglos para cada posición final de izquierda a derecha. El siguiente código implementa el algoritmo:

    int p = 0, s = 0;
    para (int k = 1; k <= n; k ++)
    {
    s = max (x [k], s + x [k]); // esta es la línea principal del código
    p = max (p, s);
    }
    cout << p << "\ n";

    El algoritmo solo contiene un bucle que pasa por la entrada, por lo que la complejidad del tiempo es O (n). Esta es también la mejor complejidad de tiempo posible, porque cualquier algoritmo para el problema tiene que examinar todos los elementos de la matriz al menos una vez.

Espero haberlo explicado bien 🙂

Algoritmo de Kadane:

incl = 0; max_so_far = 0;

para (i = 0; i

{

max_incl = max_incl + arr [i];

if (max_incl <0) max_incl = 0;

más

{

max_so_far = max (max_so_far, max_incl);

final = i;

}

}

for (j = end; max_so_far! = 0; j–)

{

max_so_far = max_so_far – arr [j];

}

volver j; // ya que apuntará al índice de inicio de la submatriz cuando la suma se convierta en 0

Complejidad de tiempo: O (n)

Espacio auxiliar: O (1)

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

Para devolver los valores del índice, tenga dos índices, digamos start y end .

Asigne un valor end dentro de la comprobación if para max_so_far . Cambie su valor al índice actual siempre que tenga un nuevo valor.

Después de obtener max_so_far , max_so_far desde el índice end hasta que tenga sum != 0 , y resta el valor del índice actual de la suma en cada iteración. Algo como

for ( j = end; sum != 0; --j)
{
sum -= ar[j]; //sum is max_so_far
}

Tu start es ahora j .

El start y el end le darán el inicio y el final de su max_so_far suma contigua máxima y max_so_far le dará la suma máxima.

Nota: Supuse que quería que su submatriz de suma máxima fuera contigua.

El enfoque más simple para construir un algoritmo es probar todas las combinaciones posibles. Por supuesto, esto sería dolorosamente lento, pero el objetivo es resolver el problema. Las optimizaciones vienen después …

# Código Python
def maxSumSubArr (arr):
#caso base
si len (arr) == 1:
volver (arr, arr [0])

#más
arrU = (arr, suma (arr))
arrL = maxSumSubArr (arr [1:]) #drop primer elemento
arrR = maxSumSubArr (arr [: – 1]) #drop último elemento

# Ahora prueba qué submatriz tiene la suma máxima
si arrU [1]> arrL [1] y arrU [1]> arrR [1]:
regreso arrU
elif arrL [1]> arrR [1]:
regreso arrL
más:
regreso arrR

Intente dibujar y visualizar el árbol de recursión para ver cómo funciona el algoritmo. Es posible que pueda encontrar algunas aceleraciones que reducirán el tiempo de ejecución.

Sugerencia: cuando dibuja el árbol de recursión, puede observar que algunas submatrices resultan más de una vez en diferentes ramas del árbol de recursión. Si es así, ¿puede reutilizar el resultado de la última vez que hizo el mismo cálculo en alguna otra rama? 🙂

Existe un algoritmo basado en programación dinámica muy eficiente para este llamado algoritmo de Kadane que resuelve este problema en O (n)
Subarray contiguo de suma más grande – GeeksforGeeks

El problema máximo de subarreglos / subsecuencias es la tarea de encontrar el subconjunto contiguo dentro de una matriz unidimensional de números que tiene la suma más grande.

Entrada:
{-1, 3, -5, 4, 6, -1, 2, -7, 13, -3}
Salida:
índice de inicio: 3
Índice final: 8
Suma: 17

Algoritmo

Matriz de 0 elementos
Si no hay ningún elemento presente en la matriz, entonces podemos decir que,
en este caso, startIndex = -1, endIndex = -1 y
maxSum = -1 (o cualquier otra notación adecuada para ningún elemento presente)

Matriz de 1 elemento
Si la matriz tiene solo un elemento, ese elemento único es el más alto en la matriz
como ese es el único elemento presente en la matriz,
en este caso, startIndex = 0, endIndex = 0 y maxSum = arr [0];

Ahora, busquemos una matriz que tenga una longitud mayor que 1 .
Antes de iterar la matriz, primero verificamos la longitud de la matriz y si es mayor que 0,
entonces solo proceda de lo contrario devuelva startIndex = -1, endIndex = -1 y maxSum = -1.

Tomemos una variable para almacenar la suma e inicialícela en 0;
int tempSum = 0;

Vamos a comenzar un ciclo de 0 a la longitud de la matriz,
elegiremos el primer elemento de la matriz y comprobaremos

tempSum = tempSum + array [i];

Si tempSum es menor que 0,
Significa que no tiene sentido incluir o considerar este elemento al máximo
la búsqueda de submatriz de suma ya que incluir este elemento hará que tempSum sea inferior a 0,
Ignore el elemento y continúe buscando el siguiente elemento.

Si tempSum es mayor que 0,
Significa que existe la posibilidad de que incluir o considerar este elemento pueda conducir a
submatriz de suma máxima, ya que incluir este elemento no está llevando tempSum a menos de 0,
Considere este elemento y continúe buscando el siguiente elemento.

Sin embargo, teniendo en cuenta que este elemento no está garantizado para formar una submatriz máxima
ya que puede disminuir la suma total que no es inferior a 0.

Por ejemplo: si la matriz es {4, -2}
Inicialmente, cuando se considera el elemento en la posición 0.
obtendremos tempSum = 4 y es mayor que 0, así que lo estamos incluyendo,

Ahora veamos el elemento en la posición 1, obtendremos tempSum = 2 (4 + -2 = -2),
En este caso tempSum = 2, que no es menor que 0, ¿deberíamos considerar esto ????
deberíamos considerar esto y probarlo porque hay posibilidades de que podamos obtener
elemento superior en la siguiente posición (por ejemplo, matriz: {4, -2, 4})
pero en nuestro caso no tenemos un elemento en la posición 2, entonces qué hacer en este caso,

Entonces, lo que haremos es tomar 2 variables,
1. maxSumTillNow, que almacenará la suma máxima hasta ahora encontrada.
2. tempSum, que almacenará la suma máxima hasta ahora encontrada y también correrá el riesgo de
agregando el siguiente elemento que puede aumentar o no maxSumTillNow.

Intentemos mapear estas variables en nuestro ejemplo,
En la primera iteración, para arr [0]
maxSumTillNow = 4
tempSum = 4

En la segunda iteración, para arr [1]
maxSumTillNow = 4
tempSum = 2

Entonces nuestro maxSumTillNow reflejará la suma máxima de subarreglos.

Explicación detallada con el programa: Subarray contiguo de suma más grande utilizando el algoritmo de Kadane.

More Interesting

Cómo formular un programa entero donde todos estén representados en un horario

¿Los ingenieros de software necesitan saber matemáticas?

Se nos dan probabilidades [matemáticas] P (A) = P (B) = P (C) \ geq 2/3 [/ matemáticas] y sabemos que [matemáticas] P (A \ cap B \ cap C) = 0 [/ mates]. ¿Qué podemos decir sobre [matemáticas] P (A) [/ matemáticas]?

¿Por qué la programación de Erlang aún no ha penetrado en el plan de estudios de ciencias de la computación como cabría esperar?

¿Cuál es el significado del teorema de Shamir?

¿Alguien ha explorado el uso de autómatas celulares 2D en una superficie esférica sintonizada para proyectar un universo 3D dentro que simule la gravedad?

Cómo escribir un programa que calcule 'b' elevado a power 'n' usando solo suma e iteración

¿Cuál es la relevancia de la computación cuántica para el problema NP = P?

¿Qué es un algoritmo eficiente para encontrar los primeros cinco números primos de diez dígitos?

Cómo usar el lema de bombeo para demostrar que [matemáticas] A = \ {www \ mid w \ in \ {a, b \} ^ * \} [/ matemáticas] no es un lenguaje normal

¿Hay algún fractal completo de Turing?

¿Es necesaria una buena comprensión matemática de los algoritmos de ML para crear software utilizando partes de él?

¿Cómo ha influido la teoría de conjuntos en el desarrollo de las estructuras de datos?

¿Cuál es la mejor manera de estudiar programación y matemáticas de libros o mirar tutoriales?

¿Cuáles son algunos temas imprescindibles en matemáticas discretas y probabilidad de programación competitiva?