目录
1 需求说明
给定序列:1,2,3,8,-1,1000, -7, 2,12, -1700,5200, 9,8, 5,1,计算其最大子序列的和
2 测试代码
int main()
{
vector<int> tmp;
int p[] = {1,2,3,8,-1,1000, -7, 2,12, -1700,5200, 9,8, 5,1};
for(int i = 0; i < sizeof(p) / sizeof(int); i++)
{
tmp.push_back(p[i]);
}
int start = 0, end = 0;
int sum = maxSubSum1(tmp, start, end);
printf("maxsum = %d, start = %d, end = %d\n", sum, start, end);
int sum2 = maxSubSum2(tmp, start, end);
printf("maxsum = %d, start = %d, end = %d\n", sum2, start, end);
int sum3 = maxSubSum3(tmp, start, end);
printf("maxsum = %d, start = %d, end = %d\n", sum3, start, end);
}
3 三种不同复杂度的算法实现
3.1 算法一:复杂度为算法:
int maxSubSum1(vector<int>& a, int& startIndex, int& endIndex)
{
//计算任意序列i到j的和,计算出最大的为止
int resault = 0;
for(int i = 0; i < a.size(); i++)
{
for(int j = i; j < a.size(); j++)
{
int thisSum = 0;
for(int k = i; k <= j; k++)
{
thisSum += a[k];
}
if(thisSum > resault)
{
resault = thisSum;
startIndex = i;
endIndex = j;
}
}
}
return resault;
}
复杂度推导过程:
最内层for循环执行j - i + 1次,中层for循环执行N - i次,最外层循环执行N次
于是由下式:
3.2 算法二:复杂度为算法:
int maxSubSum2(vector<int>& a, int& startIndex, int& endIndex)
{
int resault = 0;
for(int i = 0; i < a.size(); i++)
{
int thisSum = 0;
for(int j = i; j < a.size(); j++)
{
thisSum += a[j];
if(thisSum > resault)
{
resault = thisSum;
startIndex = i;
endIndex = j;
}
}
}
return resault;
}
推导过程:
3.3 算法3:简易算法,只计算最大和,不返回序列的位置
int maxSubSum3(vector<int>& a)
{
int resault = 0, thisSum = 0;
for(int i = 0; i < a.size(); i++)
{
thisSum += a[i];
if(thisSum > resault)
{
resault = thisSum;
}
else if(thisSum < 0)
{
thisSum = 0;
}
}
return resault;
}
算法设计核心原则为:任何负数元素不可能为最优子序列的起始元素
4 联机算法与完美算法
联机算法:只对数据进行一次扫描,数据一旦读入就不需要再被记忆;任意时刻都能对读入的子序列问题给出正确答案的算法
完美算法:仅需常量空间且以线性时间运行的联机算法