文章目录
常见时间复杂度
时间复杂度 | 说明 | 举例 |
---|---|---|
O(1) | 常数 | 217 |
O(logn) | 对数 | 4logn+12 |
O(n) | 线性 | 3n+21 |
O(nlogn) | 对数线性 | 2n+3nlogn+15 |
O(n2) | 平方 | 6n2+5n+19 |
O(n3) | 立方 | 2n3+3n2+5n+8 |
O(2n) | 指数 | 7*3n |
算法思维:解决复杂问题
衡量标准:问题的规模n
讨论的问题:当n->∞,问题能不能得到解决
算法解决的问题:当n非常大时,
普通程序不能工作:
占用空间太大了,运行时间太长了
怎么办?
需要优化算法:提出、评估满足大规模问题的优化算法
线性时间
斐波那契数列
n = 100 # 问题规模
result = [1, 2]
while len(result) < 100:
x = result[-1] + result[-2] # 计算下一个值
result.append(x) # 将新值放入列表
print(result)
# 程序需要运行3+3*(n-2),它的时间复杂度是O(n),线性时间
'''
假定以行为单位,计算运行时间
(1)(2)(3):3
(3)(4)(5):循环n-2遍,每一遍运行3行,3*(n-2)
'''
# 总运行时间T(n)=3+3*(n-2)=O(n)
# 空间复杂度S(n)=n+2=O(n)
# 改进:降低空间复杂度
n = 100
x, y = 1, 2
for i in range(n - 2):
x, y = y, x + y
print(y)
# 总运行时间T(n)=3+2*(n-2)=O(n)
# 空间复杂度S(n)=4=O(1)
迭代法
迭代法是从某个值开始,不断地利用旧值推导出新值的算法。
通常通过一个循环,不断地用某种方法从旧值产生新值。
循环到某个条件满足时,可以得到最终解。
辗转相除法求最大公约数问题
a, b = eval(input())
if a < b: a, b = b, a
while b != 0:
a, b = b, a % b # 利用旧值推导新值 最后b=0,a为最大公约数
print(a)
# 由于每两次迭代后余数最多为原来的一半,最多需要迭代2logb次,因此时间复杂度为O(logb)
穷举法
穷举法也叫暴力法,如果在问题求解时,无法找到有效的解决问题的办法,可以对所有可能的解进行逐一验证,将符合要求的解找出来。
找出质量之和为X的组合
对前面n-1个数进行循环(外循环),每次外循环,都将这个数和它后面的所有数依次进行配对(内循环)。
def find(A, X):
for i in range(len(A) - 1):
for j in range(i + 1, len(A)):
if A[i] + A[j] == X:
return i, j
return -1, -1
A = [18, 9, 25, 6, 19, 14, 8, 27, 15]
X = 22
i, j = find(A, X)
if i != -1:
print(A[i], A[j])
else:
print("没有可行解")
计算最短路径
根据排列组合,一共有432=24种不同的方法可供选择。
依据穷举法,可将这24种方法全部计算出来,然后输出最短的距离即可。
def get_dis(p1, p2):
return ((p2[0] - p1[0]) ** 2 + (p2[1] - p1[1]) ** 2) ** 0.5
A = ((100, 50), (200, 25), (50, 30), (150, 10))
min_dis = 1e10
for x1, y1 in A:
for x2, y2 in A:
if (x2, y2) == (x1, y1):
continue
for x3, y3 in A:
if (x3, y3) in ((x1, y1), (x2, y2)):
continue
for x4, y4 in A:
if (x4, y4) in ((x1, y1), (x2, y2), (x3, y3)