首先让我们用一个例子展示O(n^3)和O(n^2)在执行时间上的巨大差距!
1.如果 a+b+c=1000,且 a^2+b^2=c^2(a,b,c 为自然数),如何求出所有a、b、c可能的组合?
(1)三重循环:T(n) = O(n*n*n) = O(n3)
import time
start_time = time.time() # 用三重循环
for a in range(0,1001):
for b in range(0,1001):
for c in range(0,1001):
if a**2 + b**2 == c**2 and a+b+c == 1000:
print("a,b,c = %d,%d,%d" % (a,b,c))
end_time = time.time()
print("elapsed:%f" % (end_time - start_time))
print("complete!")
(2)两重循环:T(n) = O(n*n*(1+1)) = O(n*n) = O(n2)
2.list和dict操作的时间复杂度(即顺序表和哈希表)
接下来让我们看下两种最典型的数据结构:顺序表和哈希表在增删改查上的时间复杂度对比。
Python 字典中使用了 hash table,因此查找操作的复杂度为 O(1),而 list 实际是个数组,在 list 中,查找需要遍历整个 list,其复杂度为 O(n),因此对成员的查找访问等操作字典要比 list 更快。
3、画格子的时间复杂度
下面是《算法图解》里的一个例子,形象展示了5种常见时间复杂度的运行时长对比:
下面按从快到慢的顺序列出了你经常会遇到的5种大O运行时间。
- O(log n),也叫对数时间,这样的算法包括二分查找。
- O(n),也叫线性时间,这样的算法包括简单查找。
- O(n * log n),这样的算法包括第4章将介绍的快速排序——一种速度较快的排序算法。
- O(n^2),这样的算法包括第2章将介绍的选择排序——一种速度较慢的排序算法。
- O(n!),这样的算法包括接下来将介绍的旅行商问题的解决方案——一种非常慢的算法
假设你要绘制一个包含16格的网格,且有5种不同的算法可供选择,这些算法的运行时间如上所示。如果你选择第一种算法,绘制该网格所需的操作数将为4(log 16 = 4)。假设你每秒可执行10次操作,那么绘制该网格需要0.4秒。如果要绘制一个包含1024格的网格呢?这需要执行10(log 1024 = 10)次操作,换言之,绘制这样的网格需要1秒。这是使用第一种算法的情况。
第二种算法更慢,其运行时间为O(n)。即要绘制16个格子,需要执行16次操作;要绘制1024个格子,需要执行1024次操作。执行这些操作需要多少秒呢?
大O表示法需要注意的是:
- 算法的速度指的并非时间,而是操作数的增速。
- 谈论算法的速度时,我们说的是随着输入的增加,其运行时间将以什么样的速度增加。
- 算法的运行时间用大O表示法表示。
- O(log n)比O(n)快,当需要搜索的元素越多时,前者比后者快得越多。
4、参考链接
【1】python帮帮:https://mp.weixin.qq.com/s/AMea_T-TnpR4TkJoZO3yhQ
【2】《算法图解》:https://item.jd.com/12148832.html