恋上数据结构跟算法学习笔记总结,我是按照视频学习顺序记录的,如有错误,不吝赐教。
一.什么是算法?
- 算法就是用来解决特定问题的一系列的执行步骤
二.斐波拉契算法
- 1.什么是斐波拉契算法?
//第n位数据值 = 第n-1位数据值 + 第n-2位数据值
0,1,1,2,3,5,8,13.....
- 2.有几种方式写呢? 第一种简单方式
-(int )fib:(int) n {
//排除n=0,1 两种情况
if (n<=1) {
return n;
}
/** @算法解析=======
第n位数据值=第n-1位数据值+第n-2位数据值
*/
return [self fib:n-1]+[self fib:n-2];
}
第二种优化方案
-(int )sum2:(int) n {
//排除n=0,1 两种情况
if (n<=1) {
return n;
}
/* @算法解析=======
声明两个变量
first=0; 代表第0位的数据值
second=1; 代表第1位的数据值
i < n-1; 代表求第n位数据值的时候,需要循环计算n-1次,下标i=0,所以i<n-1
sum = first + second; 代表second后面一位等于前两位之和
first = second; 代表first往后移动一位,移到second位置上
second = sum; 代表second往后移动一位,移到sum位置上
return second; 代表返回最后一组循环结束后second移动到的位置
*
*/
int first = 0;
int second = 1;
for (int i = 0; i < n-1; i++) {
int sum = first+second;
first = second;
second = sum;
}
return second;
}
- 3.两种方式有什么不同?
- 第一种方式适用于n比较小的情况,n一旦稍微比较大时,这个算法很费时间,因为重复调用
- 第二种方式不用区分n大小,即使n比较大,这个算法也不费时间
- 两个方法的耗时时间可以通过特定工具监测,在这里我就不测了
- 斐波拉契算法时间复杂度分析 先看第一种方式的时间复杂度,可以理解为,调了几次sum函数,时间复杂度就是几,用图分析一下调用顺序
通过上图分析,调用次数n = 1+2+4+8 = 2^0 + 2^1 + 2^2 + 2^3 = 2^4 -1 = 2^(n-1) - 1 = 0.5 * 2^n - 1 时间复杂度为:O(2^n)
再来看第二种方式的时间复杂度为:O(n)
根据下图不同时间复杂度的对比,可以看出O(n) < O(2^n)
三.如何评价一个算法好坏?
- 正确性,可读性,健壮性(对不合理输入的反应能力)
- 时间复杂度(time complexity):估算程序指令的执行次数(执行时间)
- 空间复杂度(space complexity):估算所需占用的存储空间
四.大O表示法
- 一般用大O表示法来描述复杂度,它表示的是数据规模n对应的复杂度
- 使用原则忽略常数,系数,低阶,对数阶一般省略底数
- 9 = O(1)
- 2n + 1 = O(n)
- n^2 + 2n + 1 = O(n^2)
- 4n^3 + n^2 + 2n + 1 = O(n^3)
- log2n = O(logn)
- 2nlog5n = O(nlogn)
- 常见的复杂度
时间复杂度比较,越往后,说明时间复杂度越高 O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)
五.算法的优化方向
- 用尽量少的存储空间
- 用尽量少的执行步骤(执行时间)
- 根据情况,可以考虑空间换时间,时间换空间
六.多个数据模式的情况
看一下下面的算法,时间复杂度由n,k 共同决定
-(void)testn:(int)n k:(int)k {
for (int i = 0; i<n; i++) {
NSLog(@"n");
}
for (int i = 0; i<k; i++) {
NSLog(@"k");
}
}
所以上述复杂规模的时间复杂度为:O(n+k),当是复杂规模时,要把所有因素都考虑进去。
本篇先记录到次,如有错误,不吝赐教。