1. 算法概念
数据结构:变量的存储(列表、栈、队列等……)
算法:一个计算过程,解决问题的方法,是计算机的灵魂。
-
①有穷性(Finiteness):算法的有穷性是指算法必须能在执行有限个步骤之后终止;
-
②确切性(Definiteness):算法的每一步骤必须有确切的定义;
-
③输入项(Input):一个算法有0个或多个输入,以刻画运算对象的初始情况,所谓0个输 入是指算法本身定出了初始条件;
-
④输出项(Output):一个算法有一个或多个输出,以反映对输入数据加工后的结果。没 有输出的算法是毫无意义的;
-
⑤可行性(Effectiveness):算法中执行的任何计算步骤都是可以被分解为基本的可执行 的操作步,即每个计算步都可以在有限时间内完成(也称之为有效性);
-
⑥高效性(High efficiency):执行速度快,占用资源少;
-
⑦健壮性(Robustness):对数据响应正确。
2. 时间复杂度
-
常见的时间复杂度(按效率排序)
-
复杂问题的时间复杂度
-
一般来说,时间复杂度高的算法比复杂度低的算法运行速度慢,如下图
由图中我们可以看出,当 n 趋于无穷大时,O(nlogn) 的性能显然要比 O(n!) 来的高
-
代码举例
1 # O(1) 2 print('hello') 3 4 # O(n) 5 def complexn(n): 6 for i in range(n): 7 print(i) 8 9 # O(n**2) 10 def complexn2(n): 11 for i in range(n): 12 print(i) 13 for j in range(n-1): 14 print(j) 15 16 # O(log n) 17 #当算法过程中出现循环折半的时候,复杂度式子会出现log n 18 def complexlo2(n): 19 while(n >1): 20 print(n) 21 n = n//2 22 # while的分析思路: 23 # 假如n = 64的时候会输出: 24 64 25 32 26 16 27 8 28 4 29 2
# 这时候可以发现程序执行了6次
-
如何快速判断时间复杂度
-
-
循环减半的过程-》O(log n)
-
几次循环就是n的几次方的复杂度
空间复杂度
递归
-
调用自身
-
结束条件
2 .判断一下下面那些函数是递归函数?
def fun1(x): # 这个函数不是递归函数,因为它没有结束条件 print(x) fun1(x-1) def fun2(x): # 这个函数不是递归函数,因为它有了条件之后,会是死循环 if(x < 0): print(x) fun2(x+1) # 先打印后递归 def fun3(x): if(x > 0): print(x) fun3(x-1) fun3(3) # 会打印 3 2 1 # 先递归后打印 def fun4(x): if(x > 0): fun4(x-1) print(x) fun4(3) # 会打印 1 2 3
3 .递归练习题
汉诺塔问题
代码实现
'''递归练习:汉诺塔问题 解决思路: 假设有n个盘子: 1.把n-1个圆盘从A经过C移动到B 2.把第n个圆盘从A移动到C 3.把n-1个小圆盘从B经过A移动到C ''' cnt = 0 #移动次数 def hannoi(n, a, b, c): global cnt if(n == 1): print(a,'MOVE',c) cnt += 1 else: #将n-1个盘子从a经过c移动到b hannoi(n-1, a, c, b) #将最后一个大盘子从a移动到c print(a, 'MOVE', c) cnt += 1 #将n-1个盘子从b经过a移动到c hannoi(n-1, b, a, c) hannoi(3,'A柱','B柱','C柱') print('移动次数=',cnt) >>输出结果 A柱 MOVE C柱 A柱 MOVE B柱 C柱 MOVE B柱 A柱 MOVE C柱 B柱 MOVE A柱 B柱 MOVE C柱 A柱 MOVE C柱 移动次数= 7
汉诺塔移动次数递推公式为f(x)=2f(x-1)+1
经过推导移动次数为f(x)=2**x -1(n为盘子数)
推导通项公式。由f(k)=2f(k-1)+1得f(k)+1=2(f(k-1)+1),于是{f(k)+1}是首项为f(1)=1,公比为2的等比数列,求得f(k)+1 = 2^k,所以f(k) = 2^k-1