一、题目要求:
输入一个一维整形数组,数组里有正数也有负数。
一维数组首尾相接,像个一条首尾相接带子一样。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。
发表一篇博客文章讲述设计思想,出现的问题,可能的解决方案(多选)、源代码、结果截图、总结。
二、程序设计思想
对于一个数组来讲,要想求最大的子数组,是一件很简单的事,但是一旦要求时间复杂度为O(n)后,情况就不一样了。
那么怎么做呢,首先对于一个数组有三种大的情况,一种是全是正的,一种是全是负的,另外一种是有正有负的,如果全是正的或全是负的,那么很简单,全是正的时候,全部相加就是子数组和的最大值,全是负的时候,数组中最大的那个数字就是子数组的和的最大值。那么有正有负的该怎么做呢?
我就想到,申明一个最大值数组,temp变量作为中间值,如果发现当前的最大值与下一个数相加之后大于零,那么就令最大值等于最大值与下个数相加的和,如果小于最大值,并且大于0,那么就用temp加上下一个数,如果小于零,那么就令temp=0,max数组向后移一位,然后令该max重新等于零,一直重复此操作,最后在从max数组里找出最大的那个就是子数组的和的最大值。
三、源代码:
public class MaxIntArray { public static void main(String [] args){ int a[]={1,4,5,6,2}; int Max[]=new int[5]; Max[0] = 0; int i = 0;//数组下标 int j = 0;//最大值数组下标 int temp=0;//中间变量 while(i<a.length){ if(temp+a[i]>=Max[j]) { temp=temp+a[i]; Max[j]=temp; i++; } else if(temp+a[i]<Max[j]&&temp+a[i]>0) { temp=temp+a[i]; i++; } else if(temp+a[i]<=0) { i++; j++; Max[j]=0; temp=0; } } int max = Max[0]; for(int k=0;k<=j;k++){ if(Max[k]>max) { max=Max[k]; } } /*System.out.println(j); for(int k=0;k<=j;k++){ System.out.println(Max[k]); }*/ System.out.println("最大子数组和为"+max); } }
首尾相连的代码:
public class Max2 { public static void main(String [] args){ int a[]={2,4,3,-9,9,9,-1}; int b[]=new int[100]; int n=a.length; for(int i=0;i<n;i++){ b[i]=a[i]; b[i+n]=a[i]; } int Max[]=new int[10]; Max[0] = 0; int i = 0;//数组下标 int j = 0;//最大值数组下标 int temp=0;//中间变量 int q=1;//用于连续长度的计数 while(q<a.length&&i<b.length){ if(temp+b[i]>=Max[j]) { temp=temp+b[i]; Max[j]=temp; i++; q++; } else if(temp+b[i]<Max[j]&&temp+b[i]>0) { temp=temp+b[i]; i++; q++; } else if(temp+b[i]<=0) { i++; j++; Max[j]=0; temp=0; q=1; } } int max = Max[0]; for(int k=0;k<=j;k++){ if(Max[k]>max) { max=Max[k]; } } /*System.out.println(j); for(int k=0;k<=j;k++){ System.out.println(Max[k]); }*/ System.out.println("最大子数组和为"+max); } }
四、程序结果截图:
4组不同的测试用例:
首尾相连的测试用例:
五、总结:
一个人的力量终究有限,这次作业我是和许磊共同完成的,在写程序之前,我们经过了激烈的讨论,以及相当长的时间的思考,最终解决了问题。
同时,我们也切实的体会到了合作所带来的好处。