数据结构和算法引入
1 题目引入
题目:如果 a+b+c=1000,且 a2+b2=c^2(a,b,c 为自然数),如何求出所有a、b、c可能的组合?
1.1 暴力搜索
即枚举法!
import time
t0 = time.time()
for a in range(1001):
for b in range(1001):
for c in range(1001):
# if a*a + b*b == c*c and a + b + c == 1000:
if a**2 + b**2 == c**2 and a + b + c == 1000:
print(a,b,c)
t1 = time.time()
print('所需时间为: ', t1-t0)
0 500 500
200 375 425
375 200 425
500 0 500
时间复杂度:O(n^3) 立方复杂度!
运行时间为:240s左右!
1.2 方法2
a b 有了 c肯定就直接出来了!就没必要再去搜索所有的了!直接赋值!
import time
t0 = time.time()
for a in range(1001):
for b in range(1001):
c = 1000 - a - b
if a**2 + b**2 == c**2:
print(a,b,c)
t1 = time.time()
print('所需时间为: ', t1-t0)
0 500 500
200 375 425
375 200 425
500 0 500
所需时间为: 1.0195651054382324
时间复杂度:O(n^2) 平方复杂度
2 Python算法本身复杂度
timeit模块可以用来测试一小段Python代码的执行速度。
class timeit.Timer(stmt=‘pass’, setup=‘pass’, timer=)
-
Timer是测量小段代码执行速度的类。
-
stmt参数是要测试的代码语句(statment);
-
setup参数是运行代码时需要的设置;
-
timer参数是一个定时器函数,与平台有关。
Timer类中测试语句执行速度的对象方法。number参数是测试代码时的测试次数,默认为1000000次。方法返回执行代码的平均耗时,一个float类型的秒数。
2.1 list的操作测试
import timeit
def test1():
# + 操作
l = []
for i in range(1000):
l = l + [i]
def test2():
# append操作
l = []
for i in range(1000):
l.append(i)
def test3():
# 列表表达式
l = [i for i in range(1000)]
def test4():
# list方式
l = list(range(1000))
def test6():
# insert
l = []
for i in range(1000):
l.insert(0,i)
from timeit import Timer
t1 = Timer("test1()", "from __main__ import test1")
print("concat ",t1.timeit(number=1000), "seconds")
concat 1.0583139009977458 seconds
t2 = Timer("test2()", "from __main__ import test2")
print("append ",t2.timeit(number=1000), "seconds")
append 0.09553768200566992 seconds
说明append比直接加会效率更高!
t3 = Timer("test3()", "from __main__ import test3")
print("comprehension ",t3.timeit(number=1000), "seconds")
comprehension 0.04220059799263254 seconds
t4 = Timer("test4()", "from __main__ import test4")
print("list range ",t4.timeit(number=1000), "seconds")
list range 0.013673824010766111 seconds
说明用list方法会比直接列表表达式效率更高
t6 = Timer("test6()", "from __main__ import test6")
print("insert range ",t6.timeit(number=1000), "seconds")
insert range 0.31473354900663253 seconds
- 说明append比assert好!数据存储方式决定的!
- 往头部添加比往尾部添加要慢得多!
综上:list方式是最好的!
2.2 pop操作测试
# 删除第一个元素
x = list(range(2000000))
pop_zero = Timer("x.pop(0)","from __main__ import x")
print("pop_zero ",pop_zero.timeit(number=1000), "seconds")
pop_zero 1.0132593379967147 seconds
# 删除最后一个元素
x = list(range(2000000))
pop_end = Timer("x.pop()","from __main__ import x")
print("pop_end ",pop_end.timeit(number=1000), "seconds")
pop_end 7.075899338815361e-05 seconds
头部删元素比尾部删元素慢得多!
3 列表和字典内置操作的时间复杂度
3.1 列表
重点:熟悉并记住下列内置函数的复杂度
- 索引是1
- append尾部追加是1
- pop尾部删除是1
- pop指定位置删除是n
- insert指定位置插入是n
- contains查询是n