最大子段和问题
问题描述:给出一个整数数组,找出一个连续子数组(可以一个都不取和为0),使得这个连续子数组的和是所有连续子数组的和中最大的。
例如给出如下的一个数组:
-2 | 11 | -4 | 13 | -5 | -2 |
表中红色标志出来的11-4+13=20就是这个数组中的最大字段和。
首先将问题细分,用sum表示当前情况下最大子段和,用result(初始时为0)记录最终结果。先只考虑一个数:
-2 |
假设取这个数,则当前子段和sum=-2,sum<0,本着子段和最大的原则这个数肯定不取。sum=0,result=0。
增加一个数:
-2 | 11 |
再增加一个数:
-2 | 11 | -4 |
此时:sum=11-4=7,sum<result,因为最终结果肯定要记录最大的所以result仍然等于11。
再增加一个数:
-2 | 11 | -4 | 13 |
假设取13,sum=7+13=20,sum>result,result保持最大状态,result=20。
再增加一个数:
-2 | 11 | -4 | 13 | -5 |
假设取-5,sum=20-5=15,sum<result,result保持不变=20。
继续增加:
-2 | 11 | -4 | 13 | -5 | -2 |
所以最终结果result=20。
现在讨论当sum<0时:
对于第一个-2,若取该数,sum=-2。后面无论取什么数都要减去2,所以当sum<0时(可能是上述情况
取一个数就小于0了,也有可能是取了多个数,这多个数的和小于0)sum应重新置为0,从新的位置开始
重新取。
例如给出这样的一个数组:
-5 | 2 | 3 | -6 | 4 | 7 |
-5 | -1 | 4 | 7 |
在后面的sum=4+7=11,sum>result时才更新result=11。
因为数组可能比较长,数组元素又可能比较大,当多个元素加起来时可能会超出int范围,所以用long来
定义sum和result.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
//System.out.println("请输入数组长度:");
int n=sc.nextInt();
int a[]=new int[n];
//System.out.println("请输入数组的各个元素值:");
for(int i=0;i<n;i++){
a[i]=sc.nextInt();
}
long sum=0,result=0;//初始化,注意此处用long型,防止结果超出int范围
for(int i=0;i<n;i++){
if(sum>0)
sum=sum+a[i];//取a[i],将a[i]加到sum中
else
sum=a[i];//sum<0,开始从新的位置开始重新取数
result=sum>result?sum:result;//当sum>result时,更新result
}
System.out.println(result);//输出最后的最大子段和
}
}