数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
求所有子数组的和的最大值。要求时间复杂度为O(n)。
例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,
因此输出为该子数组的和18。
很容易理解,当我们加上一个正数时,和会增加;当我们加上一个负数时,和会减少。如果当前得到的和是个负数,那么这个和在接下来的累加中应该抛弃并重新清零,不然的话这个负数将会减少接下来的和。基于这样的思路,我们可以写出如下代码。
代码①:
// MaxSumOfArray.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
int MaxOfArray(int a[],int N)
{
int sum=0;
int Max=0;
for (int i=0;i<N;i++)
{
sum=0;
for(int j=i;j<N;j++)
{
sum+=a[j];
if (Max<sum)
{
Max=sum;
}
}
}
return Max;
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[]={1, -2, 3, 10, -4, 7, 2, -5};
int result = MaxOfArray(a,sizeof(a)/sizeof(int));
printf("%d",result);
getchar();
return 0;
}
输出结果:18,但是这个算法时间负责读为O(n^2)
必须有更好的方法才行
如果要求找出最大值,并且找出起始和终止位置,代码如下:
// MaxSumOfArray.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
int MaxOfArray(int a[],int N)
{
int sum=0;
int Max=0;
for (int i=0;i<N;i++)
{
sum=0;
for(int j=i;j<N;j++)
{
sum+=a[j];
if (Max<sum)
{
Max=sum;
}
}
}
return Max;
}
int MaxOfArray2(int a[],int N)
{
int sum=0;
int Max=0;
for (int i=0;i<N;i++)
{
sum+=a[i];
if(sum<0)
{
sum=0;
}
else if(sum>Max)
{
Max=sum;
}
}
return Max;
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[]={-1, -2, -3, 10, 4, -7, 2, -5};
int begin=0;
int end=0;
int result = MaxOfArray2(a,sizeof(a)/sizeof(int),&begin,&end);
//如果要求找出最大值,并且找出起始和终止位置
printf("%d , %d, %d",result,begin,end);
getchar();
return 0;
}
下面的代码,既可以找到子数组的最大和,也可以定位到是子数组是从何开始,到何截止
// getSumOfArray1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
using namespace std;
int getSum(int a[],int len,int *start,int *end)
{
int max=0,sum=0;
int start1=0,end1=0;
for (int i=0;i<len;i++)
{
sum+=a[i];
if (sum<0)
{
sum=0;
start1=i+1;
}
if (sum>max)
{
end1=i;
max=sum;
}
}
*start=start1;
*end=end1;
return max;
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[]={1,2,-4,2,3,-1,3};
int len=sizeof(a)/sizeof(int);
int start=0,end=0;
cout<<getSum(a,len,&start,&end)<<endl;
cout<<"起始位置:"<<start<<endl;
cout<<"终止位置:"<<end<<endl;
system("pause");
return 0;
}