原题:
思路:
①在动态规划的前提下,加入两个min的纪录值,和两个min和(遍历到对应位置的最大和)的纪录值
②然后遍历整个数组
③-①如果没有遇到比当前最小值(初始为0)更小的继续往后推,累加最大值
③-②如果遇到了将次小的最小值弹出,那么如果之前纪录的次小值位置的和小于0,代表那之前的元素都只是拖累(把次小值补回来之后),那么去掉之前的次小值之和,并且把次小值补回当前最小值(ThisSum+=min[1]),然后当前最大和去掉刚刚扫描到的最小值当中(ThisSum-=arr[i]),同时根据扫描值的大小将其存入min[0](最小值)或者min[1](次小值)中,并纪录当前最小值和
代码实现:
int MaxSubSum(int arr[], int len)
{
int i;
int MaxSum = NINF; //负无穷
int ThisSum = 0;
int min[2] = {0}; //用于纪录两个最小值
int minSum[2] = { 0 }; //用于纪录当最小值时的和
for (i = 0; i < len; i++)
{
ThisSum = ThisSum + arr[i];
if (arr[i] < min[1]) { //当当前元素小于较大的那个最小值
if (minSum[1] < 0) { //较大的那个最小值前的和如果为负数,那么就直接抛去较大的最小值前面的所有元素
ThisSum -= minSum[1];
}
ThisSum += min[1]; //把 大的最小值(因为这里认为这个值被删除了) 归回序列和中
minSum[1] = ThisSum; //纪录一下 较大的最小值(包括自己)之前的和
min[1] = arr[i]; //纪录当前的最小值
if (arr[i] < min[0]) { //如果现在的最小值 比 小的那个最小值要小,那么交换两个最小值的顺序
int temp = min[0];
min[0] = min[1];
min[1] = temp;
temp = minSum[0]; //最小值前的和也要交换
minSum[0] = minSum[1];
minSum[1] = minSum[0];
}
ThisSum -= arr[i]; //让和减去当前的最小值(加上那个值的负值),意指删除了该元素
}
if (ThisSum <= arr[i]) { //如果当前和小于当前值,那么全部重置,认为和只会出现在后面
ThisSum = arr[i];
min[0] = 0; //最小值也要重置,因为这里就认为现在的位置是个全新的位置了,最小值无用了
min[1] = 0;
}
if (ThisSum > MaxSum) //如果当前和大于最大值,纪录最大值
MaxSum = ThisSum;
}
return MaxSum;
}
运算结果:
两个可能的问题: