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

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

首先,求非环状的数组中子数组 最大和问题是一个动态规划的思想。

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=0,sum=0,i=0;
		   while(i<a.length)
		   {
			   if(sum>0)//sum代表了以i-1为尾子数组最大和,如果它之前位置最大和大于零,则在此基础上加上当前位置元素的值,就是以当前位置结尾的子数组的最大和
				   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=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=0,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=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=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=0,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[]={-3,8,-2,-3,12,4,6,3,-1,-2};
			int maxnotcircle=NotCircleMaxValue(a);
			int maxcircle=CircleMaxvalue(a);
	       System.out.println(maxnotcircle>maxcircle?maxnotcircle:maxcircle);

		}

	}

结果:28

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

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

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-25 03:23:51

环状连续数组,求子数组最大和的相关文章

结对开发首尾相接数组求子数组最大和

组员:燕亚峰  20122914           王童博   20122823 一.题目及要求: 返回一个整数数组中最大子数组的和 如果数组A[0]...A[j-1]首尾相邻,允许A[i-1]...A[n-1],A[0]...A[j-1]之和最大:同时返回最大子数组的位置. 二.设计思路: 对于这题本想延用一维数组的方法,不过由于数组进行了整合,始末位置无法判断.所以此种方法断然没有实现. 可以形成一个固定长度的窗口,依次相加比较. 首先将为两种情况,一种是跨越a[n-1],a[0]的.一种

首尾相接数组求子数组最大和

一.题目及要求: 返回一个整数数组中最大子数组的和 如果数组A[0]...A[j-1]首尾相邻,允许A[i-1]...A[n-1],A[0]...A[j-1]之和最大:同时返回最大子数组的位置. 二.设计思路: 对于这题本想延用一维数组的方法,不过由于数组进行了整合,始末位置无法判断.所以此种方法断然没有实现. 小伙伴曾说延用课上学生提供的方法,形成一个固定长度的窗口,依次相加比较.这不失为一个好方法.只可惜时间复杂度不是n. 于是上网查了点资料.思想有点引用网上的了.首先将为两种情况,一种是跨

二维数组求子数组之和最大值(首尾相接, 圆柱)

问题:求二维数组的子数组之和的最大值(首尾相接,即形成圆柱) 成员: 陈晨:负责代码复审和代码测试计划 王颖瑞:负责程序分析,代码编程 思路:对于这个问题,我们可以结合之前的实验(二维数组求子数组之和的最大值和首尾相连一维数组的子数组之和的最大值),把为二维数组的列扩大二倍,之后想一维数组(首尾相连)一样,把二维数组分成不同的几个二维数组.之后就分开求不同的二维数组的子数组的最大值,最后之间比较,求出总的最大值. 代码: #include<iostream> using namespace s

环形数组求子数组和最大

题目:返回一个整数数组中最大子数组的和.要求: 输入一个整形数组,数组里有正数也有负数. 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和. 如果数组A[0]……A[j-1]首尾相邻,允许A[i-1],…… A[n-1],A[0]……A[j-1]之和最大. 同时返回最大子数组的位置. 求所有子数组的和的最大值. 分析: 运用了第一次的实验返回数组的最大子数组和,就只是把环形数组变成了n次的数组. 但是我们没有保存每一次的最大值,只是比较了最大值,所以没有返回子数组的位置. #inc

Java实现:求子数组的最大和(数组)

求子数组的最大和(数组) 题目: 输入一个整形数组,数组里有正数也有负数.数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和.求所有子数组的和的最大值.要求时间复杂度为 O(n). 例如输入的数组为 1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为 3, 10, -4, 7, 2,因此输出为该子数组的和 18. 解题思路: 我觉得用户关心的的数据有两个,一个是子数组的和,还有一个是子数组具体有哪些元素,所以我们可以封装一个子数组类SubArray,成员有子数据开

求一个数组的子数组的最大和

如题:求一个数组的子数组的最大和,要求O(n)时间复杂度. 由于有了O(n)时间复杂度的限制,所以暴力求解的O(n^2)方法肯定不行.再考虑递归求一个数组a[n]的子数组的最大和,可以分解为a[i]子数组的最大和以及a[n-i-1]之间的某种情况 a[n]的子数组最大和等于a[i]子数组的最大和: a[n]的子数组最大和等于a[n-i-1]: a[n]的子数组最大和跨a[i]和a[n-i-1]: 递归实现的时间复杂度为O(nlg(n)).最后考虑时间复杂度为O(n)的动态规划实现. /** *

【编程题目】求子数组的最大和 ☆

3.求子数组的最大和(数组)题目:输入一个整形数组,数组里有正数也有负数.数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和.求所有子数组的和的最大值.要求时间复杂度为 O(n).例如输入的数组为 1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为 3, 10, -4, 7, 2,因此输出为该子数组的和 18. 算法里学过,动态规划.具体思路想不起来了,看了看书.要动态算1-i个元素中必须包括第i个元素的最大子段和C[i],A是原始序列 C[i + 1] = A[

微软算法100题03 求子数组的最大和

3.求子数组的最大和题目:输入一个整形数组,数组里有正数也有负数.数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和.求所有子数组的和的最大值.要求时间复杂度为O(n).例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,因此输出为该子数组的和18 思路:使用辅助变量max 记录子数组的最大和,从数组头开始遍历,如果数组元素与之前的总和的sum是负数,则重置sum结果为零,否则将得到的sum值与max比较 如果小于ma

[华为机试练习题]56.求子数组的最大和

题目 描述: 输入一个整形数组.数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和.求所有子数组的和的最大值. 接口 Int GetSubArraySum(Int* pIntArray,Int nCount): 规格 要求时间复杂度为O(n) 举例 例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2, 因此输出为该子数组的和18 练习阶段: 初级 代码 /*-------------------------------