题目:输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为O(n)。 例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,因此输出为该子数组的和18。
如果不考虑时间复杂度,我们可以枚举出所有子数组并求出他们的和。不过非常遗憾的是,由于长度为n的数组有O(n^2)个子数组;而且求一个长度为n的数组的和的时间复杂度为O(n)。因此这种思路的时间是O(n^3)。
本题解决思路:当我们加上一个正数时,和会增加;当我们加上一个负数时,和会减少。如果当前得到的和是个负数,那么这个和在接下来的累加中应该抛弃并重新清零,不然的话这个负数将会减少接下来的和,程序代码如下:
#include <iostream>
#include <vector>
using namespace std;
int main (void){
//定义输入数组,存储输入的数组
vector <int> data;
//定义输出结果,存储最大和子数组
vector <int> result;
//定义输入变量
int input;
//定义和值
int sum=0;
//定义遍历过程中的最大和值
int maxsum=0;
//定义最大和值对应的id
int finial_id=0;
cout<<"please enter the integer:"<<endl;
//逐位读取输入的数字,最后需要Ctrl+Z结束
while(cin>>input)
{
//将输入的数字,逐个压入到堆
data.push_back(input);
}
//计算最大和值
for(int i=0;i<data.size();i++)
{
//和值累加
sum=data[i]+sum;
//记录最大和值并保存最大和值对应的最后一个数据的id
if(sum>maxsum)
{
maxsum=sum;
finial_id=i;
}
//若此时和值大于0,将结果压入到结果堆中
if(sum>=0)
result.push_back(data[i]);
//和值小于0的时候,清除结果堆中的数据
else
{
result.clear();
sum=0;
}
}
//若最后和值和最大值一致,则此时结果堆中的数组就是对应的子数组
if(sum==maxsum)
{
cout<<"maxsum"<<maxsum<<endl;
for(int i=0;i<result.size();i++)
cout<<result[i]<<endl;
}
//若最后和值和最大值不一致,则需要找到最大值对应的子数组
else
{
cout<<"maxsum"<<maxsum<<endl;
int i=0;
//清空result数组
result.clear();
//以最大和值最后一个数据对应的id为标杆,将最大和值子数组压入到结果数组
while(maxsum>=0)
{
result.push_back(data[finial_id-i]);
maxsum=maxsum-data[finial_id-i];
if(finial_id-i==0)
break;
i++;
}
//按顺序输出结果
for(int i=0;i<result.size();i++)
cout<<result[result.size()-i-1]<<endl;
}
return 0;
}