参考课程:
清华大学博士讲解Python数据结构与算法(完整版)全套100节_哔哩哔哩_bilibili
程序=数据结构+算法
数据结构是计算机存储、组织数据的方式,是指相互之间存在一种或多种特定关系的数据元素的集合。算法是一系列解决问题的清晰指令,代表着用系统的方法描述解决问题的策略机制。也就是说,它能够对一定规范的输入,在有限时间内获得所要求的输出。
时间复杂度
算法的时间复杂度表示该算法的运行时间,通常用程序计算的次数来表示,并且因为它只是一个约数,所以一般只保留计算次数表达式中最大的量级。
例如:
print('hello world')
打印出这一字符串需要进行一次计算,所以算法的时间复杂度为O(1).
for i in range(n):
for j in range(n):
for k in range(n):
print('hello world')
在这一段程序中,每遍历1次i,就要遍历n次j;每遍历1次j,就要遍历n次k。
因此,当i被遍历n次时,j被遍历次,k被遍历
次,算法会打印
遍“hello world”,复杂度为O(
)。
那么问题来了,下面的代码:
print('hello world')
print('hello python')
print('hello pycharm')
这段代码需要进行3次计算,那么时间复杂度是O(3)吗?
并非如此。
因为时间复杂度是一个单位,计算机运行3次和运行1次的差别微乎其微,因此只要在这个单位中保留最大的量级即可。
只要是常数次计算,时间复杂度仍旧记为O(1).
同理,下面的代码
for i in range(n):
print('hello world')
for j in range(n):
print('hello world')
在这段程序中,每遍历1次i,系统就要执行1次运算,之后遍历n次j,执行n次运算。
因此每遍历n次i,系统就要执行n次运算,之后遍历次j,执行
次运算。
系统的运算次数为,但是时间复杂度只保留大的量级,因此它的时间复杂度记为O(
)。
当算法中出现循环折半时,算法的时间复杂度标记中一定有O(logn),计算机中的logn通常都是以2为底,此处省略2.这是一种时间复杂度很低的算法,编写程序的时候如果应该尽量使其出现。
while n>1:
print(n)
n=n//2
此处一直将n进行折半计算。假设运行了k次,则可知≈n,k≈0(logn),因此算法复杂度为O(logn)。
在不同的时间复杂度量级中,O(1)<O(logn)<O(n)<O()<O(
logn)<O(
)
而对于时间复杂度为O(n!),O(),O(
)的程序而言,这样的时间复杂度是计算机不能承受的,对应的问题被称为“NP-HARD”问题,需要经过非精确算法求解。
空间复杂度
与时间复杂度用来评估算法运行时间对应的,空间复杂度用来评估算法占用内存的大小。
例如,
生成几个变量,算法的时间复杂度为O(1);
生成长度为n的一维列表,算法的时间复杂度为O(n);
生成m行n列的列表,算法的时间复杂度为O(nm)。
在计算机存储技术充分发展的今天,算法时间复杂度的重要性相比以往计算机只有500M内存的年代已经大打折扣。当今的算法设计的一个重要理念是“以空间换时间”。