La "Suma máxima posterior" de la serie de programación dinámica

53. Suma máxima de suborden

Dada una matriz de enteros nums, busque una submatriz continua con la suma más grande (la submatriz contiene al menos un elemento) y devuelva la suma más grande.

Este problema no se puede resolver con una ventana deslizante, porque la matriz contiene números complejos, por lo que no se puede determinar el tamaño de la ventana.

La ventana deslizante se utiliza en la secuencia de números positivos continuos donde la suma es S

La idea se puede ver en la explicación oficial del problema, la explicación es muy clara, así que no la repetiré aquí ...
También puedes consultar labuladong

Método uno: programación dinámica

class Solution {
    
    
    public int maxSubArray(int[] nums) {
    
    
        int tmp = 0;  // tmp 表示以nums[i]为结尾时的最大子序和,我们的目的是求得所有的,然后找出最大的
        int res = nums[0];  // res表示到目前nums[i]为止,之前以 nums[k],0≤k≤i 为结尾的所有最大子序和的最大值。
        for(int each : nums){
    
    
            tmp = Math.max(tmp + each, each);
            res = Math.max(res, tmp);
        }
        return res;
    }
}

Complejidad del tiempo: O (n)

Complejidad espacial: O (1)

Método dos: divide y vencerás

class Solution {
    
    
    public class Status {
    
    
        public int lSum, rSum, mSum, iSum;

        public Status(int lSum, int rSum, int mSum, int iSum) {
    
    
            this.lSum = lSum;
            this.rSum = rSum;
            this.mSum = mSum;
            this.iSum = iSum;
        }
    }

    public int maxSubArray(int[] nums) {
    
    
        return getInfo(nums, 0, nums.length - 1).mSum;
    }

    public Status getInfo(int[] a, int l, int r) {
    
    
        if (l == r) {
    
    
            return new Status(a[l], a[l], a[l], a[l]);
        }
        int m = (l + r) >> 1;
        Status lSub = getInfo(a, l, m);
        Status rSub = getInfo(a, m + 1, r);
        return pushUp(lSub, rSub);
    }

    public Status pushUp(Status l, Status r) {
    
    
        int iSum = l.iSum + r.iSum;
        int lSum = Math.max(l.lSum, l.iSum + r.lSum);
        int rSum = Math.max(r.rSum, r.iSum + l.rSum);
        int mSum = Math.max(Math.max(l.mSum, r.mSum), l.rSum + r.lSum);
        return new Status(lSum, rSum, mSum, iSum);
    }
}

Complejidad temporal: la complejidad temporal es O (n)
Complejidad espacial: la recursividad utilizará el espacio de pila O (logn), por lo que la complejidad del espacio progresivo es O (logn)

En comparación con el "Método 1", el "Método 2" tiene la misma complejidad de tiempo, pero debido a que utiliza la recursividad y mantiene una estructura de cuatro datos, tarda un poco más en ejecutarse y la complejidad del espacio no es tan buena como el Método 1. Y Es difícil de entender. Entonces, ¿cuál es el significado de este método?

Para esta pregunta, es cierto. Pero una mirada más cercana al "Método II", que no solo puede resolver el intervalo [0, n - 1][0,n−1], también puede usarse para resolver cualquier [l, r][l,r]problema de subintervalo . Si [0, n - 1][0,n−1], después de que todo el subintervalo de información de la partición hacia abajo aparece con la memoria de almacenamiento en pila del camino hacia abajo, es decir, para construir un árbol real, podemos buscar dentro de un intervalo arbitrario en el tiempo O (logn) La respuesta , incluso podemos modificar el valor en la secuencia, hacer un mantenimiento simple, y luego aún podemos encontrar la respuesta en cualquier intervalo de tiempo O (logn). Para consultas a gran escala, la ventaja de este método es Reflejada. Este árbol es la estructura de datos mágica mencionada anteriormente: el árbol del segmento de línea.

Supongo que te gusta

Origin blog.csdn.net/weixin_44471490/article/details/109189317
Recomendado
Clasificación