一、递归与二分法
一)递归
1、递归调用的定义
递归调用:在调用一个函数的过程中,直接或间接地调用了函数本身
2、递归分为两类:直接与间接
#直接 def func(): print('from func') func() func() # 间接 def foo(): print('from foo') bar() def bar(): print('from bar') foo()
3、递归调用的特点和使用的注意点
递归调用:在调用一个函数的过程中,直接或间接地调用了函数本身 python中的递归效率低,需要在进入下一次递归时保留当前的状态 在其他语言中可以有解决方法:尾递归优化,即在函数的最后一步(而非最后一行)调用自己,尾递归优化:http://egon09.blog.51cto.com/9161406/1842475;但是python又没有尾递归,且对递归层级做了限制 #总结递归的使用: 1. 必须有一个明确的结束条件 2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少 3. 递归效率不高,递归层次过多会导致栈溢出 在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出
4、递归的执行分为两个阶段:递推(询问的过程)和回溯(回答的过程)
1 #获知age(5)的值 2 # age(5)=age(4)+2 3 # age(4)=age(3)+2 4 # age(3)=age(2)+2 5 # age(2)=age(1)+2 6 # age(1)=18 7 # 8 # age(n)=age(n-1)+2 #n>1 9 # age(1)=18 #n=1 10 11 def age(n): 12 if n == 1: 13 return 18 14 return age(n-1)+2 15 16 print(age(5))
5、可以递归的最大深度
1 #虽然可以设置,但是因为不是尾递归,仍然要保存栈,内存大小一定,不可能无限递归 2 import sys 3 sys.getrecursionlimit() ##获取目前默认递归的最大深度,默认深度是1000 4 sys.setrecursionlimit(500) ##更改默认递归的最大深度 5 n=1 6 def test(): 7 global n 8 print(n) 9 n+=1 10 test() 11 test()
6、应用场景:有许多层的列表,要取出所有元素——设置结束条件使用递归
l =[1, 2,'list' ,[3, [4, 5, 6, [7, 8, [9, 10, [11, 12, 13, [14, 15,[16,[17,]],19]]]]]]] def search(l): for item in l: # if type(item) is list: if isinstance(item,list): ##判断数据类型是否是列表 search(item) else: print(item) search(l)
二)二分法
1、二分法的产生
一个按照从小到大排列的数字列表中找到指定的数字,遍历的效率太低,用二分法(算法的一种,算法是解决问题的方法)可以极大低缩小问题规模
2、 二分法的作用:不断将列表切分成两份,减小压力
1 l = [1,2,5,6,77,1001,1165,2340] 2 def search(l,num): 3 print(l) 4 if len(l) > 1: 5 mid_index = len(l) // 2 #相除取整 6 if num > l[mid_index]: 7 #in the right 8 l = l[mid_index+1:] 9 elif num < l[mid_index]: 10 #in the left 11 l = l[:mid_index] 12 else: 13 print('find it') 14 return 15 else: 16 if l[0] == num: 17 print('find it') 18 else: 19 print('not exists') 20 return 21 search(l,num) #重复的可以放在if里面 22 search(l,77)
二、匿名函数
一)什么是匿名函数
# 有名函数 def f1(m): print(f1(3)) # 匿名函数 lambda n:n*2
二)匿名函数的应用场景
匿名函数自带return,只能使用一次 #匿名函数即没有绑定名字的函数,意味着只能使用一次就会回收 应用场景:只使用一次的功能
三)匿名函数的使用
salaries={ 'egon':3000, 'alex':10000000, 'wupeiqi':10000, 'yuanhao':2000 } def f1(k): return salaries[k]
1、max、min与 lambda结合
print(max(salaries,key=lambda k:salaries[k])) print(min(salaries,key=lambda k:salaries[k]))
2、sorted与lambda结合
print(sorted(salaries,key=lambda k:salaries[k])) print(sorted(salaries,key=lambda k:salaries[k],reverse=True))
3、map(映射)与lambda结合
将原来的元素进行处理后,重新赋值给原变量
l=['alex','egon','wzs','yuanhao'] print(list(map(lambda x:x+'123',l)))
4、reduce(合并)与lambda结合
计算0到100数字的和
1 from functools import reduce 2 # reduce(lambda 表达式,计算范围,计算的初始值) 3 res=reduce(lambda x,y:x+y,range(1,100),100) 4 print(res)
5、filter(过滤)与lambda结合
过滤出列表中以123结尾的元素
l=['alex123','egon123','wzs123','yuanhao'] print(list(filter(lambda name:name.endswith('123'),l)))
6、扩展: 拉链函数
l1=[1,2,3] s1='hello' res = zip(l1,s1) print(list(res)) res=zip(salaries.values(),salaries.keys()) print(max(res)[1])
1 t1=(111,'a') 2 t2=(11,'b',123,'c') 3 print(t1 < t2)