算法时间复杂度:事前预估算法时间开销T(n)与问题规模n的关系(T表示“time”)
算法一:逐步递增型
void Loveyou(int n)//n为问题规模
{
int i=1;//1
while(i<=n)//2
{
i++;//3
printf("I love you %d\n",i);//4
}
printf("I love you more than %d\n",n);//5
}
int main()
{
Loveyou(3000);
return 0;
}
语句频度:
1. 1次
2. 3001次
3.4 3000次
5. 1次
T(3000)=1+3001+3000*2+1
时间开销与问题规模n的关系:
T(n)=3n+3
- 问题一:是否可以简化表达式?
当n足够大时
T(n)=3n+3
T(n)=n2+3n+1000
T(n)=n3+3n+100
以上的式子可以直接保留对T(n)影响最大的一项
- 加法规则:多项相加,只保留最高阶的项,且系数变为1
- 乘法规则:多项式相乘都保留
数量级比较:
O(1)<O(log2n)<O(n)<O(nlog2n)<O(n2)<O(n3)<O(2n)<O(n!)<O(nn)
以上的比较原理是可以根据洛必达法则比较出来的
- 问题二:如果有上千行代码也需要一行一行数吗?
结论1:顺序执行的代码只会影响常数项,可以忽略
结论2:只需挑循环中一个基本操作分析它的执行次数与n的关系即可
算法二:嵌套循环型
void Loveyou(int n)
{
int i=1;
while(i<=n)
{
i++;
printf("I love you %d\n",i);
for(int j=1;j<=n;j++)
{
printf("I am man\n");
}
}
printf("I love you more than %d\n",n);
}
时间开销与问题规模n的关系:T(n)=O(n)+O(n2)=O(n2)
结论3:如果有多层循环,只需要关注最深层循环循环了多少次
算法三:指数递增型
void Loveyou(int n)
{
int i=1;
while(i<=n)
{
i=i*2;
printf("I love you %d\n",i);
}
printf("I love you more than\n");
}
计算上诉算法的时间复杂度T(n);
解答:设最深层循环的语句频度(总共循环的次数)为x,则由循环条件可知,循环结束时刚好满足:2x>n x=log2n+1,T(n)=O(x)=O(log2n)
算法四:搜索数字型
void Loveyou(int flag[],int n)
{
printf("I an iron man\n");
for(int i=0;i<n;i++)
{
if(flag[i]==n)
{
printf("I love you %d\n",n);
break;
}
}
}
最好情况:元素n在第一个位置---O(1)
最坏情况:元素n在最后一个位置---O(n)
平均情况:假设元素n在任意一个位置的概率相同 为:1/n---O(n)