笔记(一)时间复杂度
学习地址:https://mp.weixin.qq.com/s/070nYGokM96aorZn6MZTDA
https://u.geekbang.org/lesson/15?article=213888
- 时间复杂度的计算
(1)得出运行时间的函数
(2)对函数进行简化 :
①用常数1来取代所有加法常数
-
-
②修改后的函数中,只保留最高阶项
③如果最高阶项存在且不是1,则忽略这个项的系数
-
- 时间复杂度大小关系
O(1) < O(log n) < O(n) < O(nlog n) < O(n^2) < O(n ^3) < O(2^n) < O(n!) < O(n^n)
写程序的时候一定对自己的程序的时间和空间复杂度有所了解。
- 递归分析时间复杂度
对递归画出一个递归树
如个Fibonacci数列求n项和 f(n)=f(n-1) + f(n-2) fib:0 1 1 2 3 5 8 13 21 ...
直接递归求和:
int fib(int n)
{
if(n < 2)
return n;
return fib(n-1) + fib(n-2);
}

求第6个数的fib和,会计算2^6次,呈指数型,时间复杂度为o(2^n) 是相当耗时的
可以增加一个缓存 将已经计算过的数据保存。不要重复计算。
通过go语言来算一下时间:
package main
import (
"fmt"
"time"
)
func fib(n int)int{
if (n < 2) {
return n
}
return fib(n - 1) + fib(n - 2)
}
func main(){
start := time.Now()
fmt.Println(fib(40))
end := time.Since(start)
fmt.Println("run time:", end)
}
当n = 40时,运行时间为 575.960922 ms
当n = 46时,运行时间为10.158493262 s
可以看出随着n的增加,程序的运行时间增加的很多。
一般在递归的情形下有这么四种在面试和工程中使用到:
1、二分查找,一般发生在一个数列本身有序的时候,你要在有序的数列里找到你的目标数。只查一边这么下去的话,最后他的时间复杂度是log(n)。
2、如果是二叉树遍历的话,他的时间复杂度是O(n)。不通过主定理,简化的思考方式,二叉树遍历的话,我们会每一个节点都访问一次,而且仅访问一次。
3、在一个排好序的二维矩阵中进行二分查找。时间复杂度是O(n),如果是一维数组二分查找,时间复杂度是O(logn)
4、归并排序(merge sort),时间复杂度是nlogn的时间复杂度。
思考:
1、手写二叉树遍历-前、中、后序,并分析时间复杂度。
答:O(n), 这里的n代表二叉树里边的树的节点总数。通过主定理得到;或者这么说不管是前序中序后续,二叉树里边的每个节点会访问一次且仅访问一次,所以它的时间复杂度线性于二叉树的节点总数,因此是O(n)
2、图的遍历:时间复杂度是多少? 答:O(n),这里的n的话是图里所有的节点总数。
3、搜索算法:DFS、BFS的时间复杂度? 答:不管是DFS(深度优先)、BFS(广度优先),时间复杂度都是O(n),这里的N指的就是搜索空间里边的节点总数。
4、二分查找:时间复杂度是多少? 答:log(n)
浙公网安备 33010602011771号