分治:将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破分而治之。经过反复应用分治手段,可以使子问题与原问题类型一致而规模却不断缩小,最终使子问题缩小到很容易求出其解。由此引出了递归算法:直接或间接调用自身的算法称为递归算法。
递归并不是一种必须的算法,而是为了更方便的求得问题的解,所以才引入(例如前序,中序,后序遍历用递归会容易很多,而循环较复杂)。但并非一切递归函数都能用非递归方式定义,例如Ackerman函数(较复杂,不详解)。剑指offer中指出:如果面试官没有特别的要求,应聘者可以尽量多的采用递归的方法
Q1、(剑指offer面试题10)斐波那契数列:求斐波那契数列的第n项
A1、
Fibonacci(n):
if(n<=0):
return 0
if(n==1):
return 1
return Fibonacci(n-1)+Fibonacci(n-2)
此方法能解决问题,但是效率较低,在动态规划中会给出优化
Q2、(剑指offer面试题10题二)青蛙跳台阶问题:一次可以跳一次,也可以跳两次,求多少种跳法
A2、同上
Q3、汉诺塔问题:
A3、解题思路:当n=1时,把圆盘直接从塔座a转塔座移到b上。当n>=2需要c来辅助:此时将n-1个较小的圆盘依据规则移动到c上,将剩下的最大的圆盘放到b上,然后再考虑将c座上n-2个圆盘转到a,将倒数第二大的放到b上,以此类推
#a是初始塔座,b的目标塔座,c是辅助塔座
def hanoi(n,a,b,c):
if n==1:
print(a,'-->',c)
else:
hanoi(n-1,a,c,b)
print(a,'-->',c)
hanoi(n-1,c,b,a)
Q4、整数划分问题(华为笔试):将正整数n表示成一系列正整数之和(与圣诞老人分礼物,分苹果是一类问题)
A4、解题思路:假设m是划分结果的最大数。
q(n,m)
当n==1只有一种情况
当m==1表示划分后的结果最大数为1,那其他划分也都是1,就只有一种情况
当m>=n表示划分结果最大数大于n,这种情况不存在,所以是q(n,n)
当m==n。当划分中包含最大数m,那么只有一种结果。当划分中不包含最大数m,那么有q(n,m-1)种情况
当m<n。当划分中包含最大数m,后面有可能再次包含也就是q(n-m,m)。当划分中不包含最大数m,则划分中所有值都比m小, 即q(n,m-1)
其中也输出也用了递归的方法(可以把输出的递归方法加到list集合里面,然后判断长度就可以得到最终结果)
def q(n,m):
if((n<1)||(m<1)):return 0
if((n==1)||m==1):return 1
if(n<m):return q(n,n)
if(n==m):return q(n,m-1)+1
return q(n,m-1)+q(n-m,m)
def f2(n, m, string):
if n == 0:
print(string)
else:
if m>1:
f2(n, m-1, string)
if m <= n:
f2(n-m, m, str(m)+ ' '+string)
这个题也可以用动态规划来解决,后面会讲解
Q5:全排列问题(今日头条,腾讯面试题):给定一个数列,输出它的全排列
def all(A,index,end):
if(index==end):
print(A)
else:
for i in range(index,end):
A[i],A[index]=A[index],A[i]
all(A,index+1,end)
A[index],A[i]=A[i],A[index]
arr=['a','b','c']
all(arr,0,len(arr))