最大子段和问题

来源:互联网 发布:unity3d音乐播放器 编辑:程序博客网 时间:2024/05/23 14:39

问题描述:给出一个整数数组,找出一个连续子数组(可以一个都不取和为0),使得这个连续子数组的和

是所有连续子数组的和中最大的。

例如给出如下的一个数组:

-211-413-5-2表中红色标志出来的11-4+13=20就是这个数组中的最大字段和。


首先将问题细分,用sum表示当前情况下最大子段和,用result记录最终结果。先只考虑一个数:

                              -2
取这个数则字段和sum=-2,不取则sum=0,本着子段和最大的原则这个数肯定不取。

增加一个数:

           -2          11取11,sum=11,sum>result(result初始化为0),result=11.

再增加一个数:

-211-4虽然下一个数是个负数,但加上个这个数还没使sum<0,继续取(后面继续解释没使sum<0就可以继续取)

此时:sum=11-4=7,sum<result,因为最终结果肯定要记录最大的所以result仍然等于11。

再增加一个数:

-211-413sum=7+13=20,sum>result,更新result=20。

再增加一个数:

-211-413-5sum=20-5=15,sum<result,result保持不变=20。

继续增加:

-211-413-5-2sum=15-2=13,sum<result,result保持不变=20。


所以最终结果result=20。

现在讨论当sum<0时:

对于第一个-2,若取该数,sum=-2。后面无论取什么数都要减去2,所以当sum<0时(可能是上述情况

取一个数就小于0了,也有可能是取了多个数,这多个数的和小于0)sum应重新置为0,从新的位置开始

重新取。

例如给出这样的一个数组:

-523-647当取了红色标志的三个数时sum=2+3-6=-1,问题就相当于:

-5-147很明显sum应该回到初始值0,从4开始重新取(但前面取2、3、-6的过程中记下的最大结果result=5不变)

在后面的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中elsesum=a[i];//sum<0,开始从新的位置开始重新取数result=sum>result?sum:result;//当sum>result时,更新result}System.out.println(result);//输出最后的最大子段和}}






0 0
原创粉丝点击