递归入门
废话
一点废话,这篇讲解是我看电子科大数据结构与算法MOOC做的笔记。
递归
递归定义
递归指子程序(或函数)直接或间接调用自己,递归的基本思想是问题分解
def A():#递归直接调用
A()
def A():#递归间接调用
B()
def B():
A()
递归要素
- 递归边界条件:确定递归何时终止,也称为递归出口
- 递归模式:大问题是如何分解成小问题的,也称为递归体
牢记递归出口和递归体,前者决定递归何时开始归,从终止条件回归到初始情况,后者决定递归的内容,在此实现递归要实现的功能。
递归应用
递归实现阶乘
def factorial(n):
if n==0:
return 1
return n*factorial(n-1)
递归实现斐波那契数列
斐波那契数列通项公式:f(n)=f(n-1)+f(n-2),当n足够大时,f(n-1)/f(n)趋向于黄金分割比0.618。
def fibonacci(n):
if n<=1:#递归出口
return n
return fibonacci(n-1)+fibonacci(n-2)#递归体/递归内容
递归实现
- 效率低可读性高
函数调用是通过栈来实现返回地址和参数传递的,递归涉及反复的函数调用,运行效率低但函数可读性好 - 尾递归
递归关系仅存在于return之后的递归叫做尾递归 - 循环或栈实现
尾递归可以通过循环实现,其他递归可以用栈来实现
分治递归
分治递归定义
分治递归,即将要求解的较大规模的问题分割成k个更小规模的子问题,直到问题规模足够小,能轻易求出解;再将小规模问题的解合并为一个更大规模问题的解,自底向上逐步求出原问题的解。
分治思想与递归是互不相离的。
分治递归的使用条件
分治法的基本步骤
递归式复杂度计算
代换法
- 忽略技术细节
有效利用代换法要求先忽略技术细节,比如递归式T(n)=2T(n/2)+O(n)中,应忽略n、n/2可能取非整数的情况,也忽略当n足够小时复杂度趋向O(1)的情况。 - 代换法主要思想
(1)猜测解的形式
(2)通过数学归纳法找出使解真正有效的常数
T(n)=2T(n/2)+O(n)中,n个数据最多可分log2n次,每次最多处理n个数据,故猜测T(n)=O(nlog2n)
迭代法
- 思想
迭代法的思想是模拟该递归关系执行过程,从而计算算法运行时间 - 分类
迭代法又分为代数法(直接展开法)和几何法(递归树法)
直接展开法
方法:展开递归关系式并将该展开的递归关系式表达成仅依赖于n和初始条件的各项之和的形式。
递归树法
主方法
递归实例
打印整数全排列
#输入正整数n,对[1,n]进行全排列并打印所有结果
#递归实例1
def PrintPermutation(a,k,n):
if k==n:#递归边界条件
s=''
for j in a:
s+=str(j)#输出字符串
print('全排列结果为:',s)
return
else:
for i in range(k,n):#递归模式/递归体
a[i],a[k]=a[k],a[i]#循环中将第一个数的值与列表所有值交换
PrintPermutation(a,k+1,n)#调用递归函数,对k之后所有元素进行上述操作
a[i],a[k]=a[k],a[i]#保持数组值不变,继续下次循环
n=int(input('输入n的值:'))
a=[]
for i in range(1,n+1):
a.append(i)
PrintPermutation(a,0,n)