连续子序列最大和问题精讲(java实现)

package com.lihe.test.collection;


import java.util.Scanner;


public class MaxSequenceSum {

/**
* @author limingyu
* 连续子序列最大和问题:给定(可能是负的)整数序列A1,A2,...An,寻找使的值最大的序列。
* 如果所有的整数都是负的,那么连续子序列的最大和是零。要求算法复杂度为O(N^2)
* 例如输入{-2,11,-4,13,-5,2}答案为20
* 输入{1,-3,4,-2,-1,6}答案是7
*/
public static void main(String[] args) {
int[] arr = new int[]{-2,11,-4,13,-5,2};
System.out.println(maxSequence(arr));

  // int[] arr = new int[]{-2,11,-4,-13,-5,2};
  // System.out.println("maxSequence1:" + maxSequence1(arr));  
}


public static int maxSequence(int[] arr) {
int maxSum = 0;
for (int i = 0; i < arr.length; i++) {
int sum = 0;
for (int j = i; j < arr.length; j++) {
sum += arr[j]; 
if(sum > maxSum){   //每次求和都進行比較
maxSum = sum;
}
}
}
return maxSum;
}   
 
   /** 
    * 从左到右记录当前子序列的和sum,开始位置为seqStart,结束位置为seqEnd。 
    * 若currentSum不断增加,那么最大子序列的和maxSum也不断增加(不断更新maxSum,start,end)。 
    * 如果往前扫描中遇到负数,那么当前子序列的和将会减小。此时currentSum 将会小于maxSum,当然maxSum也就不更新。 
    * 如果currentSum降到0时,说明前面已经扫描的那一段就可以抛弃了,这时将currentSum置为0,并且seqStart为下一个位置。 
    * 然后,currentSum将从后面开始将这个子段进行分析,若有比当前maxSum大的子段,继续更新maxSum。这样一趟扫描结果也就出来了。  
    * 要求算法复杂度为O(N)
    */    
   public static int maxSequence1(int[] arr){  
       int maxSum = 0;  
       int currentSum = 0;   
       int seqStart = 0;//最大和子序列起始位置
       int seqEnd = 0;//最大和子序列结束位置
       for(int i = 0,j = 0; j < arr.length; j ++){  
           currentSum += arr[j];  
           if(currentSum > maxSum){  
               maxSum = currentSum;  
               seqStart = i;
               seqEnd = j; 
           }  
           /**
            * 定理:设Ai,j是满足Si,j<0的任意子序列,如果p>j,那么Ai,q不是最大连续子序列
            * 如果一个子序列的和是负的,则它不可能是最大连续子序列的一部分,因为我们可以通过不包含他来得
            * 一个更大的连续子序列。或所有与最大连续子序列相邻的连续子序列一定有负的(或0)和(否则会包含他们)
            */
           else if(currentSum <= 0){  
          //当检测到一个负的子序列时,可以让i直接增加到j+1,抛弃掉之前的负子序列,重新开始。
          i = j + 1;  
               currentSum = 0;  
           }             
       }  
       System.out.println("start :" + seqStart + " end : "+ seqEnd);  
       return maxSum;  
   }  



}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值