要求:
(1)输入一个整形数组,数组里有正数也有负数。
(2)数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
(3)如果数组A[0]……A[j-1]首尾相邻,允许A[i-1], …… A[n-1], A[0]……A[j-1]之和最大。
(4)同时返回最大子数组的位置。
(5)求所有子数组的和的最大值。要求时间复杂度为O(n)。
一、设计思想
这个问题的最优解一定是以下两种可能。
可能一:最优解没有跨过array[n-1]到array[0],即和非环形数组一样了。
可能二:最优解跨过array[n-1]到array[0],新问题。
对于第一种情况,我们可以按照非环形数组求法来求,为max1;对于第二种情况,可以将原问题转化为数组的最小子数组和问题,再用数组全部元素的和减去最小子数组和,那么结果一定是跨过a[n-1]到a[0]情况中最大的子数组和,设为max2。最终结果即为max1与max2中较大的那个。
例1:有数组5、-1、-6、8、2
求得max1=10,max2=15,则取较大的max2作为结果。
例2:有数组-6、8、1、6、-1
求得max1=15,max2=14,则取较大的max1作为结果。
二、源程序
package com.minirisoft;
import java.util.*;
public class MaxArray {
public static void main(String[] args)
{
int o1=0;
int num,i;
int sum=0;
int max;
int first=0;
int last=0;
int order=0;
Scanner cin=new Scanner(System.in);
System.out.print("请输入数组的长度:");
num=cin.nextInt();
int array[]=new int[num];
int max1=array[0];
int min=array[0];
for(i=0;i<num;i++)
{
array[i]=cin.nextInt();
}
for(i=0;i<num;i++)
{
if(sum<=0)
{
sum=array[i];
first=i;
}
else
{
sum=sum+array[i];
}
if(sum>max1)
{
max1=sum;
last=i;
}
}
System.out.println("第一种情况的最大值:"+max1);
for(i=0;i<num;i++)
{
if(sum>=0)
{
sum=array[i];
o1=i;
}
else
{
sum=sum+array[i];
}
if(sum<min)
{
min=sum;
order=i;
}
}
int sum1=0;
for(i=0;i<num;i++)
{
sum1=sum1+array[i];
}
int max2=sum1-min;
System.out.println("第二种情况的最大值:"+max2);
if(max1>max2)
{
System.out.println("和最大子数组为:");
max=max1;
for(int j=first;j<=last;j++){
System.out.println(array[j]+" ");
}
}
else
{
max=max2;
System.out.println("和最大子数组为:");
for(int j=0;j<num;j++){
if(j<o1||j>order){
System.out.println(array[j]+" ");
}
/*if(j!=order)
{
System.out.print(array[j]+" ");
}*/
}
}
System.out.println("子数组和的最大值为:"+max);
}
}
三、运行结果截图: