环状连续数组,求子数组最大和

      今天看到环状连续数组求子数组最大和的题目,看了几篇博客,但是好像有问题,可以举出反例。于是参考其他人的博客自己又总结下。
首先,求非环状的数组中子数组 最大和问题是一个动态规划的思想。

sum[i] = max(sum(i-1) + a[i], a[i]); sum[i]代表以i元素结尾的子数组的最大和,sum[i-1]代表以i-1元素结尾的子数组的最大和,a[i]代表第i个元素的值,由此公式可得,以第i个元素结尾的子数组的最大和可以由它之前的以第i-1个元素结尾的子数组的最大和推导出。如果以i-1结尾子数组的最大和sum[i-1]>0,那么sum[i-1]+a[i]则就是sum[i],如果sum[i-1]<0,则以i元素结尾的最大子数组最大和就是a[i]了。那么如果数组从头到尾以每个位置元素结尾的子数组的最大和都有了,只要比较得到其中最大的值,那么就是这个数组子数组最大和的值。

求非环形连续数组字数组最大和,代码:(1)

public static int NotCircleMaxValue(int[] a){//求非环形结构时最大和字数组
		   
		   if(null==a||a.length<=0)
		   {
			   System.out.println("数组不合法");
			    return Integer.MIN_VALUE;
		   }
		   int maxvalue=a[0],sum=0,i=0;
		   while(i<a.length)
		   {
			   if(sum>0)
				   sum+=a[i];
			   else
				   sum=a[i];
			   if(maxvalue<sum)
			   {
				   maxvalue=sum;
			   }
			   i++;
		   }
		   
		   return maxvalue;
	   }


 
求环状数组中子数组 最大和问题。 

思想:

求这个问题会有两种情况:

《1》如果拥有最大和的子数组就在a[0]与a[n-1]范围中。

《2》如果拥有最大和的子数组包含了a[0]与a[n-1],也就是跨越了这个收尾结合的地方。

因此对于这两种情况我们做两种处理:

《1》按照代码(1)求出非环形数组的子数组最大和

《2》利用上面动态规划思想,我们同样可以找到非环形结构中子数组的最小和,并且可以求得最小和是以哪个位置结束,也就是最小和结束元素的索引。然后,以该索引后的元素做代码(1)的处理。

最后,将两种情况得到的最大值进行比较,取其中较大的为最大和。

或许第二点有点费解,这个结论没有去证明,日后再查资料证明。

求子数组最小和结束位置代码,代码(2)

 public  static int getMinindex(int[] a){
		   if(null==a||a.length<=0)
		   {
			   System.out.println("数组不合法");
			    return Integer.MIN_VALUE;
		   }
		   int minvalue=a[0],sum=0,i=0,MinIndex=0;
		   while(i<a.length)
		   {
			   if(sum<0)
				   sum+=a[i];
			   else
				   sum=a[i];
			   if(minvalue>sum)
			   {
				   minvalue=sum;
				   MinIndex=i;
			   }
			   i++;
		   }
		   
		   return MinIndex;
		   
	   }


求以最小和结束位置为开始元素的子数组最大和,代码(3)

public static int CircleMaxvalue(int[] a){
	        int minIndex=getMinindex(a);
	        if(minIndex<=Integer.MIN_VALUE)
	        {
	        	return Integer.MIN_VALUE;
	        }
	        int start=minIndex+1;
	        int maxvalue=a[start%a.length],sum=0;
	        for(int i=start;(i%a.length)!=minIndex;i++)
	        {
	        	if(sum>0)
	        		sum+=a[i%a.length];
	        	else
	        		sum=a[i%a.length];
	        	if(maxvalue<sum)
	        	{
	        		maxvalue=sum;
	        	}
	        	
	        	
	        }
	        return maxvalue;
	   }


 下面是整体代码: 

public class test {

	   public static int NotCircleMaxValue(int[] a){//求非环形结构时最大和字数组
		   
		   if(null==a||a.length<=0)
		   {
			   System.out.println("数组不合法");
			    return Integer.MIN_VALUE;
		   }
		   int maxvalue=a[0],sum=0,i=0;
		   while(i<a.length)
		   {
			   if(sum>0)
				   sum+=a[i];
			   else
				   sum=a[i];
			   if(maxvalue<sum)
			   {
				   maxvalue=sum;
			   }
			   i++;
		   }
		   
		   return maxvalue;
	   }
		
	   public  static int getMinindex(int[] a){
		   if(null==a||a.length<=0)
		   {
			   System.out.println("数组不合法");
			    return Integer.MIN_VALUE;
		   }
		   int minvalue=a[0],sum=0,i=0,MinIndex=0;
		   while(i<a.length)
		   {
			   if(sum<0)
				   sum+=a[i];
			   else
				   sum=a[i];
			   if(minvalue>sum)
			   {
				   minvalue=sum;
				   MinIndex=i;
			   }
			   i++;
		   }
		   
		   return MinIndex;
		   
	   }
	    public static int CircleMaxvalue(int[] a){
	        int minIndex=getMinindex(a);
	        if(minIndex<=Integer.MIN_VALUE)
	        {
	        	return Integer.MIN_VALUE;
	        }
	        int start=minIndex+1;
	        int maxvalue=a[start%a.length],sum=0;
	        for(int i=start;(i%a.length)!=minIndex;i++)
	        {
	        	if(sum>0)
	        		sum+=a[i%a.length];
	        	else
	        		sum=a[i%a.length];
	        	if(maxvalue<sum)
	        	{
	        		maxvalue=sum;
	        	}
	        	
	        	
	        }
	        return maxvalue;
	   }
	   

		public static void main(String[] args) {
			int a[]={-1,8,-2,-3,12,4,6,3,-1,-2};
			int maxnotcircle=NotCircleMaxValue(a);
			int maxcircle=CircleMaxvalue(a);
	       System.out.println(maxnotcircle>maxcircle?maxnotcircle:maxcircle);
	        
		}
		
	}

 

结果:29

顺便列出几个测试其他博客代码出现问题的数组序列

{-3,8,-2,-3,12,4,6,3,-1,-2};
{1,-4,8,-2,-3,12,4,6,3,-1,-2};

 



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值