问题定义:对于一包含n个浮点数的向量,求其连续序列的最大值
解法一:枚举法是一种显而易见的做法,其时间复杂度为O(n*n*n)
int MaxSubsequence(int n,int x[])
{
// insert code here...
int maxsofar = 0;
int i = 0;
int j = 0;
int k = 0;
for (i = 0; i < n; i++)
{
for (j = i; j < n; j++)
{
int sum = 0;
for (k = i; k < j+1; k++)
{
sum += x[k];
maxsofar = max(maxsofar,sum);
}
}
}
return maxsofar;
}
这段代发简洁明了,但时间复杂度为立方,运行速度太慢
解法二:在解法一的基础上对其进行优化,总和sum可以由第二循环得出,不需要再嵌套一个循环来计算总和。保存状态避免重复计算。这样使时间复杂度降到了平方。
int MaxSubsequence(int n,int x[])
{
// insert code here...
int maxsofar = 0;
int i = 0;
int j = 0;
for (i = 0; i < n; i++)
{
int sum = 0;
for (j = i; j < n; j++)
{
sum += x[j];
maxsofar = max(maxsofar, sum);
}
}
return maxsofar;
}
另外一种类似的算法是对信息进行预处理。数组cumarr的第i个元素为x[0…i]的累加和,所以x[i…j]中各个数的总和可以通过计算cumarr[i]-cumarr[i-1]得到。起事件复杂度也为平法。
int MaxSubsequence(int n,int x[])
{
// insert code here...
int maxsofar = 0;
int i = 0;
int j = 0;
int sum = 0;
int cumarr[] = {0,0,0,0,0,0,0};
for (i = 0; i < n; i++)
{
cumarr[i] = cumarr[i-1] + x[i];
}
maxsofar = 0;
for (i = 0; i < n; i++) {
for (j = i; j < n; j++) {
sum = cumarr[j] - cumarr[i-1];
maxsofar = max(maxsofar,sum);
}
}
return maxsofar;
}
解法三:分治法。要解决规模为n的问题,可递归地解决两个规模近似为n/2的子问题,然后对它们的答案进行合并以得到整个问题的答案。
int MaxSubsequence(int l,int r,int x[])
{
// insert code here...
int lmax = 0;
int rmax = 0;
int m = 0;
int sum = 0;
if (l > r)
{
return 0;
}
if (l == r)
{
return max(0, x[l]);
}
m = (l + r) / 2;
int i = 0;
for (i = m ;i >= 1; i--)
{
sum += x[i];
lmax = max(lmax, sum);
}
sum = 0;
for (i = m + 1; i <= r; i++)
{
sum += x[i];
rmax = max(rmax, sum);
}
return max3(lmax + rmax, MaxSubsequence(l,m,x),MaxSubsequence(m+1,r,x));
}
解法四:扫描算法
int MaxSubsequence(int n,int x[])
{
int maxsofar = 0;
int maxendinghere = 0;
for( int i =0;i < n ;i++)
{
maxendinghere = max(maxendinghere + x[i], 0);
maxsofar = max(maxsofar,maxendinghere);
}
return maxsofar;
}