微信公众号:珷玞的日常
递归是一种思想,它只是将解决方案思路更清晰,并没有性能上的优势。
递归满足的三个条件
-
一个问题的解可以分解为几个子问题的解
-
这个问题和分解后的子问题,除了数据规模不同求解思路完全相同
-
存在递归终止条件
如何写好递归
-
递归代码两个关键点:写出递归表达式和终止条件。所以只要理清这两点,递归就写出来了。
-
写递归的时候,将它抽象成一个递推公式,不用想一层层的调用关系。
举例说明,如一个问题A可以分解为BC两个子问题。BC也可以进行相同的分解。但是此时不需要考虑这个,在递归中,你只要考虑清楚A和BC这一层的关系并用表达式表示出来就可以,不要企图了解整个的调用过程,那样毫无益处,我深受其害。
例题
1.汉诺塔问题
在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,任何时候,在小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。问应该如何操作?
很经典的例题,递归方法:先将n-1个盘子从x经z到y,然后将最后一个盘从x放到z,然后将n-1个盘子从y经x到z。
def han(num,x,y,z):
if num == 1:
print(x,'->',z)
else:
han(num-1,x,z,y)
print(x,'->',z)
han(num-1,y,x,z)
2.走楼梯问题(斐波那契数列数列)
假如这里有 n 个台阶,每次你可以跨 1 个台阶或者 2 个,请问走这 n 个台阶有多少种走法?
对于第 n 个台阶,我们可以最后一步跨2个台阶也可以跨一个台阶,所以递归公式 f(n) = f(n-1) + f(n-2),终止条件就是1个或者是2个台阶的时候。 和裴波那切数列公式相同,终止条件的值略微不同。
def louti(n):
if n == 1:
return 1
if n == 2:
return 2
else:
return louti(n-1) + louti(n-2)
3.倒叙输出
给定一个非负数,倒序输出
这个比较简单,从个位数向前输出,所以递归公式 f(n) = n + f(n/10),终止条件:n 为个位数时
def daoxvshuchu(n):
if n < 10:
print(n)
else:
print(n%10)
daoxvshuchu(int(n/10))
4.某个数字各位数相加,一直到结果为个数
给定一个非负整数 num,反复将各个位上的数字相加,直到结果为一位数。
def addDigits(n):
sum = 0
for i in list(str(n)):
sum += int(i)
if sum >= 10:
return addDigits(sum)
else:
return sum