目录
场景
我在做LeetCode第四题时,发现该题对算法的时间复杂度有要求,而我对“时间复杂度”这个概念一知半解,正好借机学习一下。
名词概念
百度百科
时间复杂性,又称时间复杂度,算法的时间复杂度是一个函数,它定性描述该算法的运行时间。这是一个代表算法输入值的字符串的长度的函数。时间复杂度常用大O符号表述,不包括这个函数的低阶项和首项系数。使用这种方式时,时间复杂度可被称为是渐进的,亦即考察输入值大小趋近无穷时的情况。
通俗理解
所谓时间复杂度就是体现算法时间成本的一个值,用大写的O来表示,我们通常假设一条语句的执行时间是相近的,因此可用算法中语句总执行次数来代表算法执行时间,求解一个算法的时间复杂度实际上就是求解算法中语句的执行次数。
常见算法、代码块时间复杂度分析
非循环、递归
def say_hello(name):
print('hello', name)
调用一次该函数,print语句执行一次,且执行次数不随参数改变而增加,时间复杂度为O(1)
for循环
def say_hello(n):
for i in range(n):
print('hello')
调用一次该函数,print语句执行n次,时间复杂度为O(n)
(这里为方便表达,只看print语句执行次数,实际上print代表的是一个非递归、非循环的代码块)
while循环
def say_hello(n):
i = 0
while i < n:
print('hello')
i = i + 1
调用一次该函数,print语句执行n次,时间复杂度为O(n)
def say_hello(n):
i = 1
while i < n:
print('hello')
i = i * 2
要判断调用一次该函数,判断print语句执行多少次,只需要看循环终止时的情况即可,此时设执行了x次,则有下式:
因此执行次数
时间复杂度为
选择排序
def selection_sort(data_list):
n = len(data_list)
for i in range(0, n - 1):
for j in range(i + 1, n):
if data_list[i] > data_list[j]:
data_list[i], data_list[j] = data_list[j], data_list[i]
return data_list
时间复杂度为
二分查找
def binary_search(target, data_list):
n = len(data_list)
data_list.sort()
left = data_list[0]
right = data_list[-1]
mid = (left + right)/2
while mid != target:
if mid > target:
right = mid
else:
left = mid
mid = (left + right) / 2
return data_list.index(mid)
在计算算法复杂度时,要抱有“最坏打算”。对应到二分查找算法中,要假设查找的数位于排序后的列表首部或者尾部,这样查找时需要定位到最后两个元素,在其中选出目标值。这时假设循环内部代码运行次数为x,列表长度为n,则:
因此执行次数
时间复杂度为
结语
我们用算法的时间复杂度体现算法的时间成本,求解一个算法的时间复杂度实际上就是求解算法中语句的执行次数。且这个概念一般用在含有递归、循环的算法中(要不然直接是O(1)了)。但并不是所有for(while)循环时间复杂度都一样,需要具体分析。