最大子段和问题

最大子段和问题

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

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

-211-413-5-2

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


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

-2          




    假设取这个数,则当前子段和sum=-2,sum<0,本着子段和最大的原则这个数肯定不取。sum=0,result=0。


增加一个数:

-211        
    假设取11,sum=11,sum>result,因为result记录最大结果,所以result=11。


再增加一个数:

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

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


再增加一个数:

-211-413        

    假设取13,sum=7+13=20,sum>result,result保持最大状态,result=20。

再增加一个数:

-211-413-5  

    假设取-5,sum=20-5=15,sum<result,result保持不变=20。

继续增加:

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






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值