LeetCode01 Suma máxima de subarreglos contiguos (programación dinámica)

Suma máxima de subarreglos consecutivos

Ingrese una matriz de enteros. Uno o más enteros consecutivos en la matriz forman una submatriz. Encuentre el valor máximo de la suma de todas las submatrices.

La complejidad de tiempo requerida es O (n).

Ejemplo 1:

Entrada: nums = [-2,1, -3,4, -1,2,1, -5,4]
Salida: 6
Explicación: La suma de submatrices consecutivas [4, -1,2,1] es el más grande, que es 6.

inmediato:

1 <= longitud de arr. <= 10 ^ 5
-100 <= arr [i] <= 100

Análisis de programación dinámica:

Idea general: Defina una matriz de programación dinámica dp con el mismo tamaño que la matriz de destino num. Después del recorrido, el valor de dp [i] es la suma máxima de las submatrices continuas que terminan en el elemento num [i]. El principio de implementación es como sigue

Definición de estado:

1. Deje que la lista de programación dinámica dp, dp [i] represente la suma máxima de subarreglos consecutivos que terminan con números de elemento [i] .

Por qué definir la suma máxima dp [i] debe contener el elemento nums [i]: para asegurar la corrección de dp [i] recursivamente a dp [i + 1];

Si no se incluye nums [i], el requisito de submatriz continua de la pregunta no se cumplirá durante la recursividad.

2. Transferencia de la ecuación: si dp [i-1] ≤0, significa que dp [i-1] tiene una contribución negativa a dp [i], es decir, dp [i-1] + nums [i] no es tan bueno como nums [i] sí mismo Big.

Cuando dp [i-1]> 0: ejecutar dp [i] = dp [i- 1] + nums [i];

Cuando dp [i -1] ≤0: ejecutar dp [i] = nums [i];

3. Estado inicial:

Dp [0] = nums [0], es decir, la suma máxima de submatrices consecutivas que terminan en nums [0] es nums [0].

4. Valor de retorno:

Devuelve el valor máximo en la lista dp, que representa el valor máximo global.

Inserte la descripción de la imagen aquí

public int maxSubArray1(int[] nums){
    
    //暴力破解2优化,O(n^2)
        int n = -100;
        for (int i = 1; i < nums.length; i++) {
    
    
            int sum = 0;
            for (int j = i; j <= nums.length; j++){
    
    
                sum += nums[j];
                if (sum > n){
    
    
                    n = sum;
                }
            }
        }
        return n;
    }
public int maxSubArray2(int[] nums){
    
    //动态规划
        
        //创建一个同样大小的数组dp[i]表示以元素num[i]为结尾的连续子数组最大和
        int[] dp = new int[nums.length];
        dp[0]=nums[0];//初始化dp[0]
        for(int j = 1;j<nums.length;j++){
    
    
            //判断条件,dp[j-1]>0表示以元素num[i]为结尾的连续子数组最大和大于0
            // 即可对之后组成更大的连续子数组有正贡献
            //dp[j-1]<0,表示以元素num[i]为结尾的连续子数组最大和小于0,
            // 不再参与之后的连续子数组,子数组从新积累
            if(dp[j-1]>0){
    
    
                dp[j] = dp[j-1]+nums[j];
            }else{
    
    
                dp[j] = nums[j];
            }
        }
        int max = Integer.MIN_VALUE;
        for(int i = 0;i<dp.length;i++){
    
    //遍历dp,找到最大值
            if(dp[i]>max)
                max = dp[i];
        }
        return max;
    }

public int maxSubArray3(int[] nums) {
    
    //同样的功能大佬的代码简单到离谱,阿巴阿巴
        int res = nums[0];
        for(int i = 1; i < nums.length; i++) {
    
    
            nums[i] += Math.max(nums[i - 1], 0);
            res = Math.max(res, nums[i]);
        }
        return res;
    }

public class MaxSubArray {
    
    
    public static void main(String[] args) {
    
    
        Solution solution = new Solution();
        int[] arr = new int[]{
    
    -2,1,-3,4,-1,2,1,-5,4};//结果为6,ok
        System.out.println(solution.maxSubArray3(arr));
    }
}

Resumen: Comenzando con la programación dinámica. Al principio, incluso la solución de fuerza bruta más simple no se escribía de forma independiente. Ahora la idea de resolver estos problemas es repentinamente clara, lo cual es demasiado poderoso.

El agrietamiento por fuerza bruta es un bucle doble que compara el tamaño de la suma de cada subarreglo, comenzando desde 0 [0], [0,1], [0,1,2], hasta [0,1,2, ... n ], y luego desde Comenzar en 1, [1], [1,2], [1,2,3] hasta [1,2, ... n], y luego comenzar en 2 ...

suma (0,0)
suma (0,1) suma (1,1)
suma (0,2) suma (1,2) suma (2,2)
suma (0,3) suma (1,3) suma (2,3)
... ... ...

--------------------------------------->

La idea de programación dinámica de este problema es encontrar el subarreglo más grande de cada arreglo que termina en num [i] y almacenarlo en el arreglo dp, y luego atravesar dp para encontrar el máximo

Max
suma (0,0) dp [0]
suma (0,1) suma (1,1) dp [1]
suma (0,2) suma (1,2) suma (2,2) dp [2]
suma (0,3) suma (1,3) suma (2,3) dp [3]
... ... ... dp [j]

Método de cálculo de dp máximo [j]

dp [j] = dp [j-1] + números [j]; dp [j-1]> 0

dp [j] = números [j]; dp [j-1] <0

Puede comprender este método calculando los ejemplos dados por usted mismo.

Supongo que te gusta

Origin blog.csdn.net/weixin_44529429/article/details/114136531
Recomendado
Clasificación