俗话说,大事化小。递归算法也是分治的思想。我国古代的愚公移山,就是这种递归。子又生孙,孙又生子。
递归的精髓主要是把握好如下三个方面:
1、明确递归终止条件;
2、给出递归终止时的处理办法;
3、提取重复的逻辑,缩小问题规模。
1). 明确递归终止条件
我们知道,递归就是有去有回,既然这样,那么必然应该有一个明确的临界点,程序一旦到达了这个临界点,就不用继续往下递去而是开始实实在在的归来。换句话说,该临界点就是一种简单情境,可以防止无限递归。
2). 给出递归终止时的处理办法
我们刚刚说到,在递归的临界点存在一种简单情境,在这种简单情境下,我们应该直接给出问题的解决方案。一般地,在这种情境下,问题的解决方案是直观的、容易的。
3). 提取重复的逻辑,缩小问题规模*
我们在阐述递归思想内涵时谈到,递归问题必须可以分解为若干个规模较小、与原问题形式相同的子问题,这些子问题可以用相同的解题思路来解决。从程序实现的角度而言,我们需要抽象出一个干净利落的重复的逻辑,以便使用相同的方式解决子问题。
递归算法常用来解决结构相似的问题。
所谓结构相似,是指构成原问题的子问题与原问题在结构上相似,可以用类似的方法解决。具体地,整个问题的解决,可以分为两部分:第一部分是一些特殊情况,有直接的解法;第二部分与原问题相似,但比原问题的规模小,并且依赖第一部分的结果。
本质上,递归是把一个不能或不好解决的大问题转化成一个或几个小问题,再把这些小问题进一步分解成更小的问题,直至每个小问题都可以直接解决。
实际上,递归会将前面所有调用的函数暂时挂起,直到递归终止条件给出明确的结果后,才会将所有挂起的内容进行反向计算。其实,递归也可以看作是一种反向计算的过程,前面调用递归的过程只是将表达式罗列出来,待终止条件出现后,才依次从后向前倒序计算前面挂起的内容,最后将所有的结果一起返回。
fact(n) = n! = 1 * 2 * 3 * 4 * ......* (n-1) * n = n * fact(n-1)
fact(n)
,可以表示为 n * fact(n - 1)
,只有**n=1
**时需要进行特殊处理;image
def factorial(n):
res = 1
for i in range(2, n+1):
res *= i
return res
print(factorial(4))
24
def factorial(n):
if n == 0 or n == 1:
return 1
else:
return (n * factorial(n - 1))
print(factorial(5))
120
factorial(5) # 第 1 次调用使用 5
5 * factorial(4) # 第 2 次调用使用 4
5 * (4 * factorial(3)) # 第 3 次调用使用 3
5 * (4 * (3 * factorial(2))) # 第 4 次调用使用 2
5 * (4 * (3 * (2 * factorial(1)))) # 第 5 次调用使用 1
5 * (4 * (3 * (2 * 1))) # 从第 5 次调用返回
5 * (4 * (3 * 2)) # 从第 4 次调用返回
5 * (4 * 6) # 从第 3次调用返回
5 * 24 # 从第 2 次调用返回
120
七、尾递归优化
def factorial(n):
return fact_iter(n, 1)
def fact_iter(n, product):
if n == 1:
return product
return fact_iter(n - 1, n * product)
print(factorial(5))
120
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(10))
55
def n_sum(a, n):
if n == 1:
return a
return n_sum(a, n - 1) + n * a
print(n_sum(2, 5))
30
def quick_sort(n):
if len(n) < 2:
return n
else:
pivot = n[0]
left = [x for x in n[1:] if x < pivot]
right = [x for x in n[1:] if x > pivot]
return quick_sort(left) + [x for x in n if x == n[0]] + quick_sort(right)
print(quick_sort([5,11,3,5,8,2,6,7,3]))
[2, 3, 3, 5, 5, 6, 7, 8, 11]