提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
最后有思维导图总结哟
如何评判一个算法优劣
这天,热爱学习的小明和小亮闲的无聊,在课间
给斐波那契数列(1,1,2,3,5,8…)的计算方式各自写了一个算法
小明写了
int Fibo(int n)
{
if(n<3)
{
return 1;
}
return Fibo(n-1)+Fibo(n-2);
}
小亮用这个方式
int Fibo (int n )
{
int first = 1;
int sec = 1;
if(n<3)
{
return sec;
}
for(int i = 3;i<=n;i++)
{
int temp = sec;
sec = first+sec;
first = temp;
}
return sec;
}
他们想要比较一下两个算法的优劣,从代码行数来看,小明更胜一筹,因为比较少,但是事实真是如此吗? 我们要引入复杂度的概念来评价两个方法的好坏
复杂度有两个组成部分,时间复杂度和空间复杂度
时间复杂度,用来衡量一个算法运行的快慢
空间复杂度则是用来衡量一个算法运行需要的额外的空间
通过这两个标准来描述一个算法的时间特性和空间特性
具体我们接下来仔细剖析
时间复杂度
当小明用机器去跑他递归的算法的时候,发现 n = 50 计算机要跑很长一段时间才能显示结果,但是小明觉得,每次从思路构造到代码,然后都得上机器去跑才能知道一个算法好不好,是很麻烦的。
小明觉得,如果把代码中的每条语句的运行时间都看成是1个单位,那我通过计算代码执行了多少次,是不是就能够拟合一个算法运行的时间了?
这是我们定义: 算法中的基本操作的执行次数,为算法的时间复杂度
这时小明突发奇想,随便写了一组循环,他好奇这个算法的时间复杂度数多少
他定义了一个 count 来观察到底执行了多少步
void Fun1(int N)
{
int count = 0;
for(int i = 0;i<N;i++)
{
for(int j = 0;j<N;j++)
{
count++;
}
}
for(int k = 0;k<2*N;k++)
{
count++;
}
int M = 10;
while(M--)
{
count++;
}
printf("%d\n",count);
}
然后他发现 count = N^2+2*N+10;
此时count 就是时间复杂度,
随后小明发现
当 N= 10 , count = 130
当 N = 100 count = 10210
当 N = 1000 count = 1002010
他发现,N 越大,count 越接近 N^2
他想忽略掉这个N^2 的系数,小亮觉得不行,这不够严谨
随后上课铃打了,格子衫老师 张三缓步走了进来
小明立马问到张三面前
张三说,当然可以,时间复杂度的计算本身就是估算,我们只要关注影响最大的系数就可以了,而且前人已经利用 大O(读欧)渐进表