《编程之美》第2.14节:求数组中的子数组之和的最大值
题目:有一个有N个元素组成的一维数组,这个数组中当然有很多子数组,那么子数组之和的最大值是多少?
解法:从头到尾遍历整个数组,不断加和,如果临时和temp<0了,则清零,否则继续加。
代码如下:
#include<iostream>
#include<algorithm>
using namespace std;
int subarrySum(int *A,int N)//返回要排除的值
{
int result=INT_MIN;
int temp=0;
for(int i=0;i<N;i++)
{
temp+=A[i];
if(temp>result)
result=temp;
if(temp<0)
temp=0;
}
return result;
}
int main()
{
int A[6]={-9,-2,-3,-5,-3,-8};
cout<<subarrySum(A,6)<<endl;
system("pause");
return 0;
}
测试用例:
1,-2,3,5,-3,-2 输出结果:8
0,-2,3,5,-1,2 输出结果:9
-9,-2,-3,-5,-3,-8 输出结果:-2
题目2:如果数组首尾相邻,使其和最大,怎么办?
解法:只需要在原来的基础上添加从头开始和从尾开始的最大值之和,如果比原来的值大,则返回,如果比原来值小,则返回原来的结果。
代码:
#include<iostream>
#include<algorithm>
using namespace std;
int subarrySum(int *A,int N)//返回要排除的值
{
int result=INT_MIN;
int temp=0;
for(int i=0;i<N;i++)
{
temp+=A[i];
if(temp>result)
result=temp;
if(temp<0)
temp=0;
}
temp=0;
int firstResult=INT_MIN,lastResult=INT_MIN;
int end=0;
for(int i=0;i<N;i++)
{
temp+=A[i];
if(temp>firstResult)
{
firstResult=temp;
end=i;
}
}
temp=0;
for(int i=N-1;i>end;i--)
{
temp+=A[i];
if(temp>lastResult)
lastResult=temp;
}
return max(result,firstResult+lastResult);
}
int main()
{
int A[6]={1,2,-3,-5,-3,3};
cout<<subarrySum(A,6)<<endl;
system("pause");
return 0;
}
问题三:如果要返回最大子数组的位置,应该如何改变,能否保证O(N)的算法复杂度?
解法:只需要保存最后一个元素的下标,然后再计算一次结果即可,复杂度仍然是O(N)。
代码:
#include<iostream>
#include<algorithm>
using namespace std;
pair<int,int> subarrySum(int *A,int N)//返回要排除的值
{
int result=INT_MIN;
int temp=0,index=-1;
for(int i=0;i<N;i++)
{
temp+=A[i];
if(temp>result)
{
result=temp;
index=i;
}
if(temp<0)
temp=0;
}
temp=0;
int firstResult=INT_MIN,lastResult=INT_MIN;
int end=0,firstIndex=-1,lastIndex=-1;
for(int i=0;i<N;i++)
{
temp+=A[i];
if(temp>firstResult)
{
firstResult=temp;
end=i;
firstIndex=i;
}
}
temp=0;
for(int i=N-1;i>end;i--)
{
temp+=A[i];
if(temp>lastResult)
{
lastResult=temp;
lastIndex=i;
}
}
if(result<firstResult+lastResult)
return pair<int,int>(lastIndex,firstIndex);
else
{
temp=0;
int i=0;
for(i=index;temp!=result;i--)
{
temp+=A[i];
}
return pair<int,int>(i,index);
}
}
int main()
{
int A[6]={1,2,-3,-5,-3,3};
pair<int,int>result=subarrySum(A,6);
cout<<result.first<<" "<<result.second<<endl;
system("pause");
return 0;
}