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
1. Des idées simples
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
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);
}
}