解决问题方法的效率与算法的巧妙程度有关,描述算法的时候我们主要关心解决问题所采用的思想,而不是具体实现细节。什么是好的算法?有两个指标:空间复杂度S(n)(根据算法写成的程序在执行时占用存储单元的长度)和时间复杂度T(n)(根据算法写成的程序在执行时耗费时间的长度)。
1.1 算法
算法的五个基本特征:
输入、输出、有穷性、确定性(每一条指令充分明确)、可行性
复杂度的渐进表示法(上界下界没有明显的界定):
表示时间复杂度的上界,存在常数, 使得当 时,有
表示时间复杂度的下界,存在常数, 使得当 时,有
表示同时有和
算法复杂度分析小窍门:
已分别知道两段算法的复杂度,那么将两个算法相加的复杂度为这两段算法中最大的那个复杂度,那么将两段算法相乘(嵌套)的复杂度则为两段算法复杂度的乘积。
如果此段算法有关K阶多项式,那么苏那发复杂度只与K项有关,其他项可以忽略不计。
对于循环的时间复杂度等于循环的次数乘以循环体内代码的复杂度
结构的复杂度取决于的条件判断复杂度和两个分枝部分的复杂度,总体复杂度取三者中最大。
1.2 实例:最大子列和问题
//算法1:复杂度为N的立方
int MaxSubseqSum1(int A[], int N) //A[]表示数组,N表示数组元素个数
{
int ThisSum, MaxSum = 0;
for (int i = 0; i < N; i++)
{
for (int j = i; j < N; j++)
{
ThisSum = 0;
for (int k = i; k <= j; k++)
{
ThisSum += A[k];
}
if (ThisSum>MaxSum)
{
MaxSum = ThisSum;
}
}
}
return MaxSum;
}
//算法2:复杂度为N的平方
int MaxSubseqSum1(int A[], int N) //A[]表示数组,N表示数组元素个数
{
int ThisSum, MaxSum = 0;
for (int i = 0; i < N; i++)
{
ThisSum = 0;
for (int j = i; j < N; j++)
{
ThisSum += A[j];
if (ThisSum>MaxSum)
{
MaxSum = ThisSum;
}
}
}
return MaxSum;
}
算法3:在线处理,复杂度为N
int MaxSubseqSum1(int A[], int N) //A[]表示数组,N表示数组元素个数
{
int ThisSum=0, MaxSum = 0;
for (int i = 0; i < N; i++)
{
ThisSum += A[i]; //向右累加
if (ThisSum>MaxSum)
MaxSum = ThisSum; //发现更大的和则更新结果
else if (ThisSum < 0)
ThisSum = 0; //子序列和为负,则加后面的数,数会更小,所以直接抛弃,从下个数开始重新加
}
return MaxSum;
}