De simple a difícil, comencemos con el problema más simple:
Dada una matriz de enteros, ¿cuál es la suma de la sub-matriz más grande? Se requiere que la matriz sea continua.
Ejemplo de entrada: nums = [-3,4, -1,2,1, -5,4]
Muestra de salida: 6, es decir, la suma de submatrices consecutivas [4, -1,2,1] es la más grande
La idea es simple:
Puede ser DP, pero no es necesario. Se puede entender de la siguiente manera: cuando la suma de la matriz existente es mayor que 0, debe contribuir a la suma en este momento, por lo que se acumula ( if sum > 0 : sum += nums[i]
) en base a ella ; cuando la suma de la matriz existente es menor que 0 , entonces debería ser Encender otra estufa ( if sum < 0 : sum = nums[i]
).
El código también es simple:
class Solution {
public int maxSubArray(int[] nums) {
int max = nums[0];
int sum = nums[0];
for (int i = 1; i < nums.length; i++) {
sum = nums[i] + (sum > 0 ? sum : 0);
max = Math.max(max, sum);
}
return max;
}
}
Además, si desea la posición de matriz más grande en lugar de la suma de matriz más grande:
La idea no es difícil:
Todavía es necesario mantener el valor máximo max, matriz y suma; establezca un inicio para indicar el límite izquierdo de la matriz, y el límite derecho es la posición actual i, no es necesario establecer variables específicamente;
Considere una pregunta importante, ¿cuándo comenzará a actualizarse? La actualización comienza al comenzar de nuevo porque la suma es menor que 0.
el código se muestra a continuación:
class Solution {
public int[] maxSubArray(int[] nums) {
int start = 0;
int sum = nums[0];
int max = nums[0];
int[] res = new int[2];
for (int i = 1; i < nums.length; i++) {
if (sum > 0) {
// 之前的数组和有"贡献",因此在其基础上累加
sum += nums[i];
} else {
// 之前的数组无"贡献",因此另起炉灶
sum = nums[i];
start = i;
}
if (sum > max) {
max = sum;
res[0] = start;
res[1] = i;
}
}
return res;
}
}
El problema es ascender, cuando la matriz se convierte en una matriz, cómo encontrar el valor máximo y su posición:
Dada una matriz M × N, devuelve la posición de la submatriz más grande, que requiere continuidad. El formato de valor de retorno es una matriz [r1, c1, r2, c2].
La idea le hará darse cuenta de repente: si fusionamos filas consecutivas en una fila, ¿no se convierte en un problema de múltiples submatrices más grandes?
Mirando la imagen, la idea del código es clara:
Establezca un límite superior superior y un límite inferior inferior, combine las líneas entre ([top, bottom]) e intente actualizar el valor máximo; el "arriba y abajo" del resultado final son los límites superior e inferior actuales, y las "izquierda y derecha" son las más grandes en la solución. Extraer cuando el problema de la submatriz.
Al fusionar filas, se pueden realizar el prefijo y la optimización , es decir, se generan un prefijo y una matriz para cada columna.
El código final es el siguiente, que sigue siendo lo suficientemente elegante:
class Solution_6789 {
public int[] getMaxMatrix(int[][] matrix) {
int m = matrix.length;
int n = matrix[0].length;
int max = matrix[0][0]; // 全局最大值
int[] res = new int[4]; // 最终结果
// 构造列的前缀和
int[][] preSum = new int[m + 1][n];
for (int i = 1; i < m + 1; i++) {
for (int j = 0; j < n; j++) {
preSum[i][j] = preSum[i - 1][j] + matrix[i - 1][j];
}
}
// 合并行
for (int top = 0; top < m; top++) {
for (int bottom = top; bottom < m; bottom++) {
// 构造一维矩阵
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = preSum[bottom + 1][i] - preSum[top][i];
}
// 最大子数组问题
int start = 0;
int sum = arr[0];
for (int i = 1; i < n; i++) {
if (sum > 0) {
sum += arr[i];
} else {
sum = arr[i];
start = i;
}
if (sum > max) {
max = sum;
res[0] = top;
res[1] = start;
res[2] = bottom;
res[3] = i;
}
}
}
}
return res;
}
}
FIN FIN E N D