Programmation dynamique : somme maximale des sous-tableaux

Introduction

Cet article se concentre sur une famille de problèmes : somme maximale de sous-réseaux et somme maximale de sous-réseaux circulaires. La question vient de LeetCode.

LC : 53 sous-tableaux et questions

Étant donné un tableau d'entiers nums, trouvez un sous-tableau contigu avec la somme maximale (le sous-tableau contient au moins un élément) et renvoyez sa somme maximale.

Cette idée est relativement simple. Envisagez de calculer la somme des préfixes de chaque position : preSum . Lorsque vous passez à la position suivante, comparez si preSum+curNum est supérieur à curSum. S'il est supérieur, alors preSum+=n, sinon preSum=n.
Après chaque comparaison, la valeur maximale doit être enregistrée.
Il s'agit en fait d'une stratégie gourmande. Si curNum plus le préfixe avant que la position ne devienne plus petite, alors la sous-séquence de la somme maximale devrait redémarrer à partir de la position actuelle.

class Solution {
    
    
    public int maxSubArray(int[] nums) {
    
    
        int max = nums[0], preSum = nums[0];
        for (int i = 1; i < nums.length; i++) {
    
    
            int n = nums[i];
            preSum = Math.max(preSum+n, n);
            max = max > preSum ? max : preSum;
        }
        return max;
    }
}

LC 918. Somme maximale des sous-réseaux circulaires

insérez la description de l'image ici

1. Des idées simples

insérez la description de l'image ici

class Solution {
    
    
    public static int maxSubarraySumCircular(int[] nums) {
    
    
        int len = nums.length;
        int preSum = 0, maxSum = nums[0];
        for (int i = 0; i < len; i++) {
    
    
            preSum = nums[i];
            for (int j = i+1; j < len + i; j++) {
    
    
                int idx = j % len;
                preSum = Math.max(preSum + nums[idx], nums[idx]);
                maxSum = Math.max(preSum, maxSum);
            }
        }
        return maxSum;
    }
}

Le résultat expirera.

Idées d'optimisation

insérez la description de l'image ici

class Solution {
    
    
    public static int maxSubarraySumCircular(int[] nums) {
    
    
        int preSum = 0, maxSum = nums[0], sum = 0, minSum = 0;
        // 最优解中不涉及环
        for (int i = 0; i < nums.length; i++) {
    
    
            int n = nums[i];
            sum += n;
            preSum = Math.max(preSum + n, n);
            maxSum = Math.max(preSum, maxSum);
        }
        // 如果有环,则说明在数组内部有一个最长的最小子序列,把它找出并去掉(找出负数)
        preSum = 0;
        for (int i = 1; i < nums.length-1; i++) {
    
    
            preSum = Math.min(preSum + nums[i], 0);
            minSum = Math.min(preSum, minSum);
        }
        return Math.max(sum-minSum, maxSum);
    }
}

Je suppose que tu aimes

Origine blog.csdn.net/qq_38684427/article/details/119959940
conseillé
Classement