14天阅读挑战赛
目录
- 前言
- 一 几类时间复杂度
- 二 兔子数列
- 1.问题分析
- 2.方法1
- 3.方法2
- 4.方法3
- 最后
前言
这篇文章是《趣学算法》的读书笔记,也对数据结构与算法的初步介绍,阅读这篇文章,我会带你改进一个算法。
一 几类时间复杂度
常见的算法时间复杂度有以下几类。
- 常数阶。
常数阶算法的运行次数是一个常数,如5、20、100。常数阶算法的时间复杂度通常用O(1)表示。 - 多项式阶
很多算法的时间复杂度是多项式,通常用O(n)、O(n2)、0(n3)等表示。 - 指数阶
指数阶算法的运行效率极差,程序员往往像躲“恶魔”一样避开这种算法。指数阶算法的时间复杂度通常用O(2n)、O(n!)、O(nn)等表示。 - 对数阶
对数阶算法的运行效率较高,通常用O(logn)、O(nlogn)等表示。
指数阶增量随着x的增加而急剧增加,而对数阶增长缓慢。它们之间的关系如下:
O(1)< O(logn)< O(n)< O(nlogn) <O(n2)< O(n3)<O(2n) <O(n!)< O(nn)
在设计算法时,我们要注意算法复杂度增量的问题,尽量避免爆炸级增量。
二 兔子数列
假设第1个月有1对初生的兔子,第2个月进入成熟期,第3个月开始生育兔子,而1对成熟的兔子每月会生1对兔子,兔子永不死去… .那么,由1对初生的兔子开始,12个月后会有多少对兔子呢?
兔子数列即斐波那契数列,它的发明者是意大利数学家莱奥纳尔多斐波那契(Leonardo Fibonacci, 1170-1250) 。1202年, 莱奥纳尔多撰写了《算盘全书》 (Liber Abaci) ,该书是一部较全面的初等数学著作。书中系统地介绍了印度一阿拉伯数码及 其演算法则,以及中国的“盈不足术”;此外还引入了负数,并研究了一些简单的一次同余式组。
1.问题分析
-
不妨拿新出生的1对小兔子分析。
第1个月,小兔子①没有繁殖能力,所以还是1对。
第2个月,小兔子①进入成熟期,仍然是1对。
第3个月,兔子①生了1对小兔子②,于是这个共有2 (1+1=2) 对兔子。
第4个月,兔子①又生了1对小兔子③,因此共有3 (1+2=3) 对兔子。
第5个月,兔子①又生了1对小兔子④,而在第3个月出生的兔子②也生下了1对小兔子⑤,因此共有5 (2+3=5) 对兔子。
第6个月,兔子①②③各生下了1对小兔子,新生的3对兔子加上原有的5对兔子,这个月共有8 (3+5=8) 对兔子。 -
可以画图理解一下
-
如此一来,我们可以设计第一种算法
2.方法1
//算法1
int Fib1(int n){if(n==1||n==2) return 1;return Fib1(n-1)+Fib1(n-2);
}
- 但是,这个算法的时间复杂度是指数阶的,需要进行改进
3.方法2
- 要计算第n个数,我们需要知道前两项的值,不妨用数组试试。将n前面的数据都记录在数组里
int Fib2(int n){ int *F=new int[n+1];//定义一个长度为n+1的数组,空间尚未使用F[1]=1;F[2]=1;for(int i=3;i<=n;i++)F[i]=F[i-1]+F[i-2];return F[n];
}
- 如此一来,算法的时间复杂度变成了O(N),空间复杂度也是O(N)。
还能改进么?
4.方法3
- 其实我们只需要记录n前面的两项就可以了,为什么不用替换的方法呢?只需要定义三个变量,让他们不停的互换、相加不就行么
int Fib3(int n){if(n==1||n==2) return 1;int s1=1; //用s1和s2记录前面的两项int s2=1;for(int i=3;i<=n;i++){int tmp=s1+s2;s1=s2;s2=tmp;}return s2;
}
- 如此一来,空间复杂度还是O(N),但是空间复杂度变成了O(1).
最后
博主码文不易,如果觉得这篇文章对你有帮助的话,可以点赞、收藏、关注。
你的支持是我创作的最大动力!