一 递归的概念
递归算法是指直接或间接调用自身的算法,递归函数是用函数自身给出定义的函数。递归的优势在于能够使函数的定义和算法的描述简捷且易于理解
,使用递归技术可以解决许多复杂问题。递归可以分为两类:基于归纳法
的递归和基于分治法
的递归。
二 归纳法
求解规模为n的问题P(n),设a1是问题P(1)的解,且对所有的k,1<k<n,若ak是问题P(k)的解,则P(ak)是问题P(k+1)的解。其中,P(ak)是对ak的某种运算或处理。
其求解过程为:
- 为求问题 P(n) 的解 an,先求问题 P(n-1) 的解 an-1,再对 an-1 进行 p(an-1) 运算或处理,得到 an;
- 为求问题 P(n-1) 的解 an-1,先求问题 P(n-2) 的解 an-2,再对 an-2 进行 p(an-2) 运算或处理,得到 an-1;
- 如此不断地进行递归求解,直到得到 P(1) 的解 a1 为止。
- 当得到 P(1) 的解之后,再回过头,不断地把所得到的解进行 p 运算或处理,直到得到 P(n) 的解为止 。
常见的用基于归纳法实现的递归算法有:Fibonacci数列、Hanoi塔问题、计算阶乘 n!、二叉树的定义或遍历算法等。
1 计算阶乘函数 n!
阶乘函数的归纳定义式如下所示:
int factorial(int n)
{
if(n == 0) return 1;
else return n * factorial(n-1);
}
2 整数划分问题
问题描述:将正整数 n 表示成一系列正整数之和称为整数的划分。n = n1 + n2 +……+ nk,其中 n1 >= n2 >= n3 >=……>= nk,k>=1。正整数n的不同划分个数称为正整数n的划分数,记作P(n),求整数 n 划分数P(n)称为整数划分问题。
解题思路:
定义两个函数,q(n,m) 和 r(n,m)。
- q(n,m):正整数n的划分中
加数 ≤ m
的划分数。- r(n,m):正整数 n 的划分中
加数 含m 而不含 > m
的所有划分数。
例如,求正整数 6 的划分数P(6),q(6,2) = 4,r(6,2) = 3。其值分别为下图的红框和蓝框。
在整数6的划分中,包含了以下几种情况:
- 包含5而不含大于5的划分有:5+1,即
r(6,5) = 1
- 包含4而不含大于4的划分有:4+2,4+1+1,即
r(6,4) = 2
- 包含3而不含大于3的划分有:3+3,3+2+1,3+1+1+1,即
r(6,3) = 3
- 以此类推,最终可以得出:
q(6,5) = r(6,5) + r(6,4) + r(6,3) + r(6,2) + r(6,1) = r(6,5) + q(6,4)
总结递推式得到 q(n, m) 与 r(n, m)的关系:q(n, m) = q(n, m - 1) + r(n, m)
和 r(n, m) = q(n-m, m)
。由此可以得出 q(n, m) = q(n, m-1) + q(n-m, m)
,即 正整数n的最大加数不大于m 的划分由 m-1的划分和 m的划分两部分组成。那么 P(n) = q(n, n) = q(n, n-1) + 1 可以通过以下递归方式实现。
int q(int n, int m)
{
if((n < 1) || (m < 1)) {
// 超出边界的置0