题目:输入一个整形数组,数组里有整数也有负数。数组中一个或连续多个整数组成一个子数组。求所有子数组的和的最大值和其序列的值。要求时间复杂度为O(N)。例如输入数组为{1,-2,3,10,-4,7,2,5},最后输出的最大该子数组的和为18。
方案一:最直观的方法就是列举出数组中所有的子数列,然后对应的每个子数列进行求和。最后再找出最大的一个。对于n个元素的数组,有n(n+1)/2 个子数列。
最快的时间复杂度为:O(N*N)。
如果i=0,就是第一项;如果f(i-1)<=0,那么就将舍弃前面的子数列,因为加起来会使后面的自数列的值<=自身子数列的值,所以舍弃。
方案一:最直观的方法就是列举出数组中所有的子数列,然后对应的每个子数列进行求和。最后再找出最大的一个。对于n个元素的数组,有n(n+1)/2 个子数列。
最快的时间复杂度为:O(N*N)。
方案二:O(N)时间复杂度的算法。根据数组找出相应的规律,减少相应的计算量。以上面的数组为例,具体分析如下:
如果i=0,就是第一项;如果f(i-1)<=0,那么就将舍弃前面的子数列,因为加起来会使后面的自数列的值<=自身子数列的值,所以舍弃。
如果i不等于0,且f(i-1)>0,那么它会使后面的自数列的值>自身子数列的值,所以保留。
用公式表示如下:
#include <iostream>
using namespace std;
int arr[8]={1,-2,3,10,-4,7,2,-5};
bool IsInvalidInput=false;
int FindGreatestSumOfSubArray(int *array,int length)
{
if(NULL==array || length<=0)
{
IsInvalidInput=true;
return 0;
}
IsInvalidInput=false;
int CurSum=0;
int nGreatestSum=array[0];
for(int i=0;i<length;i++)
{
if(CurSum<=0)
CurSum=array[i];
else
CurSum+=array[i];
if(CurSum>nGreatestSum)
nGreatestSum=CurSum;
}
return nGreatestSum;
}
int main()
{
int Greatest=FindGreatestSumOfSubArray(arr,8);
if(!IsInvalidInput)//用这个全局变量来标记输入是否有效是必要的,因为函数的返回值有可能返回0,那么我们要利用这个标志来判断是程序正常的返回0,还是输入无效返回0;
cout<<"Greastest: "<<Greatest<<endl;
else
cout<<"THE INPUT IS INVALID!"<<endl;
system("pause");
return 0;
}
运行结果:
#include <iostream>
using namespace std;
#include <deque>
int arr[8]={1,-2,3,10,-4,7,2,-5};
bool IsInvalidInput=false;
deque<int> de;
deque<int>::iterator it;
int FindGreatestSumOfSubArray(int *array,int length)
{
int start=0;
int end=0;
if(NULL==array || length<=0)
{
IsInvalidInput=true;
return 0;
}
IsInvalidInput=false;
int CurSum=0;
int nGreatestSum=array[0];
for(int i=0;i<length;i++)
{
if(CurSum<=0)
{
CurSum=array[i];
start=i;
}
else
CurSum+=array[i];
if(CurSum>=nGreatestSum)
{
nGreatestSum=CurSum;
end=i;
}
}
while(start<=end)
{
de.push_back(array[start]);
start++;
}
return nGreatestSum;
}
int main()
{
cout<<"原数组序列:";
for(int i=0;i<8;i++)
cout<<arr[i]<<" ";
cout<<endl;
int Greatest=FindGreatestSumOfSubArray(arr,8);
if(!IsInvalidInput)//用这个全局变量来标记输入是否有效是必要的,因为函数的返回值有可能返回0,那么我们要利用这个标志来判断是程序正常的返回0,还是输入无效返回0;
cout<<"Greastest: "<<Greatest<<endl;
else
cout<<"THE INPUT IS INVALID!"<<endl;
cout<<"最长子序列为:";
for(it=de.begin();it!=de.end();it++)
cout<<*it<<" ";
cout<<endl;
system("pause");
return 0;
}
运行结果: