递推与递归
递推思想
递推的定义:
递推算法是一种用若干步可重复运算来描述复杂问题的方法。递推是序列计算中的一种常用算法。通常是通过计算前面的一些项来得出序列中的指定项的值。
简而言之就是从一致的规律一步步推向未知的信息。
由递推的定义可以得到递推算法所需要两个基本条件:
(1) 递推式
(2) 初始条件或边界条件
以斐波那契数列为例:
众所周知,在斐波那契数列中,后一项等于前面两项之和,归纳一下即可得到这样一个式子: f[i] = f[i - 1] + f[i - 2]
,这个式子就称为 递推式
。从第三项开始往后,每一项都符合这个式子。
因为斐波那契数列是从第 2 项开始的序列,那么初始条件,就是最前面两项,即 f[1] = f[2] = 1
。
像这样知道递推式以及初始条件,从初始条件开始往上顺推直到求得目标解的思想就是递推。
递归思想
递归的定义:
递归,就是在运行的过程中自己调用自己。
构成递归需要具备的条件:
- 子问题须与原始问题为同样的事情,且更为简单;
- 不能无限制地调用本身,须有一个出口,化简为非递归状况处理。
递归有点类似于 分治 ,递归地思想是 把一个大的问题拆分成一个个小的问题,通过不断递归调用解决小问题,直到小问题全部被解决从而解决原来的大问题。
由此也可以得到递归算法所需要的两个条件:
(1) 递推关系(递归函数)
(2) 边界条件
一般的递归写法都是 构造一个递归函数(一个可以自己调用自己的函数就成为递归函数),并设置好递归终止条件,写好处理数据部分,再重复调用自己,最后将每一部分结果合并处理。
以下题为例
给出一个自然数 n,最开始数列中唯一的一项就是 n,可以对这个数列进行下述操作,生成新的数列:
·在原数列的末端加入一个自然数,但是这个自然数不能超过该数列最后一个数字的一半
比如说,输入数字 6,符合这样性质的数列有 [6]、[6 1]、[6 2]、[6 2 1]、[6 3]、[6 3 1].
递归思想:将 n = 6 的问题,分解为 3 个(n = 3, 2, 1)小问题,n = 3 时,再向下取整分解为 n = 1 的问题,n = 2 也是分解为 n = 1 的问题,直到 n = 1 时,没法继续分解,则返回上一层(n = 2)接收到所有小问题的答案,合并统计处理获得这个规模下的答案,再继续返回上一层,直到求得问题的解,最后输出答案。
核心代码:
void solve(int x)
{
if (x == 1) return 1; //递归出口
int ans = 1;
for (int i = 1; i <= x / 2; i++)
ans += solve(i); //递归
return ans;
}
有些问题使用递推和递归都能解决,但有些问题只能将大问题分割成小问题,却很难建立起递推式,在这种情况下应当使用递归策略。