数据结构与算法之美(个人笔记)- 算法性能分析_复杂度分析(上)

本人在购买极客学院王争老师的《数据结构与算法之美》后,觉得里面的内容还不错,适合新手入门,故将自己的学习笔记整理了下,做个记录,供学习使用,另里面存在个人理解,难保会有差错,欢迎大家在评论区讨论,侵删。

极客学院专栏地址:https://time.geekbang.org/column/intro/126?gk_activity=0


笔记目录: https://blog.csdn.net/lxfHaHaHa/article/details/101039494


复杂度分析

设计算法和数据结构的时候,我们会尽量让代码运行得更快,更省存储空间,那么,用什么方法来衡量呢?这里就要用到我们今天要讲的内容:时间复杂度分析、空间复杂度分析。

1 时间复杂度

1.1 公式分析

先把公式附上:
在这里插入图片描述

  • n代表数据规模的大小
  • T(n)代表代码执行的时间
  • f(n)表示每行代码执行的总数之和,因为是个以n为自变量的函数,故用f(n)表示
  • O(大写的o)用来表示T(n)与f(n)成正比

第一个例子:

int cal(int n) {   
	int sum = 0;   
	int i = 1;   
	for (; i <= n; ++i) {     
		sum = sum + i;  
	 }   
	 return sum; 
}

假设每一行代码运行的时间是一样的,为一个时间单位Unit_time,则第2、3、7行各运行了1个Unit_time,第4、5行各运行了n遍,即最后为2n+3个时间单位。

T(n)=O(f(n))=O(2n+3)

第二个例子:

int cal(int n) {  
	int sum = 0;   
	int i = 1;   
	int j = 1;   
	for (; i <= n; ++i) {    
		 j = 1;    
		  for (; j <= n; ++j) {       
		  	sum = sum +  i * j;     
		  }   
	} 
}

假设每一行代码运行的时间是一样的,为一个时间单位Unit_time,则第2、3、4行各运行了1个Unit_time,第5、6行各运行了n遍,第7、8行各运行了n*n遍,即最后为2n^2+2n+3个时间单位。

T(n)=O(f(n))=O(2n^2+2n+3)

好了,我们现在引出时间复杂度的概念,所有代码的执行时间T(n)与每行代码的执行次数n成正比,即T(n)=O(f(n))
这里的大O时间复杂度表示法,实际上并不具体表示代码真正的执行时间,而是表示代码执行时间随数据规模增长的变化趋势,所以,也叫作渐进时间复杂度(asymptotic time complexity),简称时间复杂度
另外,当数据量规模n变大,公式中的低阶、常量、系数三部分并不左右增长趋势,所以都可以忽略。我们只需要记录一个最大量级就可以了。

第一个例子的时间复杂度为:T(n)=O(n)
第一个例子的时间复杂度为: T(n)=O(n^2)

1.2 方法

这里,给了三个trick:

  • 只关注循环次数最多的一段代码
  • 加法法则:总复杂度等于量级最大的那段代码的复杂度
  • 乘法法则:嵌套代码的时间复杂度由嵌套内外的时间复杂度相乘。如上面的例子2是有两个for循环嵌套起来的,其实可以看成g1(g2(n)),故最后为n*n
1.3 常见时间复杂度公式

数据结构与算法之美(个人笔记)- 算法性能分析_复杂度分析(上)_第1张图片

  • 粗略的分为,多项式量级和非多项式量级,只有O(2^n)和O(n!)是非多项式量级
  • 随着数据规模n的增加,非多项式量级(NP复杂度)会爆发式增长,耗费时间也越来越多,是效率非常低的算法
  • O(1)是常量级时间复杂度的一种表达方式,不是指只运行了一行,运行了100行、一万行这种数目一定的都是O(1)
  • O(logn)是对数时间复杂度,因为系数可以省略,所以log2n、log3n这种都说logn
  • O(m+n)这种是有两个数据规模存在,因为事先不能确定二者的量级,故不能简单的用加法法则表示

2 空间复杂度

既然时间复杂度是指渐进时间复杂度,那么相似的,空间复杂度也是相似空间复杂度(asymptotic space complexity),表示算法的存储空间与数据规模之间的增长关系

void print(int n) {
  int i = 0;
  int[] a = new int[n];
  for (i; i = 0; --i) {
    print out a[i]
  }
}

第2行申请一个存储单位i,第三行申请n个存储单位,故空间复杂度为O(n)

Tips: 常见的空间复杂度就是 O(1)、O(n)、O(n2 ),像 O(logn)、O(nlogn) 这样的对数阶复杂度平时都用不到。

3.小结

  • 时间复杂度:渐进时间复杂度,表示算法的执行时间与数据规模之间的增长关系
  • 空间复杂度:渐进空间复杂度,表示算法的存储空间与数据规模之间的增长关系

数据结构与算法之美(个人笔记)- 算法性能分析_复杂度分析(上)_第2张图片

4.课后思考

有人说,我们项目之前都会进行性能测试,再做代码的时间复杂度、空间复杂度分析,是不是多此一举呢?而且,每段代码都分析一下时间复杂度、空间复杂度,是不是很浪费时间呢?你怎么看待这个问题呢?

不是这样的,我觉得作为一个合格的开发人员,要对开发有敬畏之心。
像厨师想炒出色香味俱全的菜肴一样,我们对code也要有追求。
当你打出时间空间复杂度方面都很优秀的代码的时候,你会觉得很自豪,就像士兵胜战而归,美人笑颜相对。
而且,时不时的考虑复杂度方面的问题,对改进算法的方向能有一个大致的把握,对自我能力的提升也是很有帮助的。

你可能感兴趣的:(数据结构与算法之美)