[Clásico de la entrevista] De una dimensión a dos dimensiones, desde la submatriz más grande a la submatriz más grande

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?

Inserte la descripción de la imagen aquí
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

Supongo que te gusta

Origin blog.csdn.net/m0_46202073/article/details/115175436
Recomendado
Clasificación