这个应该放在前面上的,只不过一cha忘了,今天我们把递归学习完。
递归和递推名字很像,很多递归的入门题都可以用递推AC,但是递归也是一种很多问题的解法,是必不可少的一个知识点,话不多说,直接如题。
【基础问题】
n的阶乘可表示为 n! =123*……(n-1)n,1! = 1。例如3的阶乘3!=123 =6。输入一个整数n(n<=15);
输出n的阶乘。
解题思路:
设:n的阶乘为f(n),观察可知f(n) = n * f(n-1)
我们用递推先来解一下:
#include <iostream>
#include <sstream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <stack>
#include <list>
#include <limits.h>
using namespace std;
long long f[N];
int main()
{
int num;
cin >> num;
f[1] = 1;
for (int i = 2; i <= num; i++)
{
f[i] = i * f[i - 1];
}
cout << f[num] << endl;
return 0;
}
先把递推的写法先放在这,等会我们再看这个递归是在怎么一步步得到答案的:
#include <iostream>
#include <sstream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <stack>
#include <list>
#include <limits.h>
using namespace std;
int f(int n);
int main()
{
int num;
cin >> num;
cout << f(num) << endl;
return 0;
}
int f(int n)
{
if (n == 1) return 1;
else return n * f(n - 1);
}
这个是上面的阶乘递归程序的示意图:
递归公式就是“递”的过程
递归边界就是“归”的实现
但是要注意“归”要先执行,不然就会运行了递归公式以后再“归”这是我们已经与正确答案擦肩而过了。
我们再写一道题,他是递推的经典题,也是递归的经典题——斐波那契数列。
#include <iostream>
#include <sstream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <stack>
#include <list>
#include <limits.h>
using namespace std;
int Fib(int n);
int main()
{
int num;
cin >> num;
cout << Fib(num) << endl;
return 0;
}
int Fib(int n)
{
if (n <= 2) return 1;
return Fib(n - 1) + Fib(n - 2);
}
总结一下递归:
什么是递归: 一个函数在定义过程中,直接或间接的调用自身称为递归.其中直接调用自己称为直接递归,而
a调
用b,b又调用a的递归称为间接递归
递归算法的特点: 递归问题必须可以分解为若干个规模较小,与原问题形式相同的子问题,这些子问题可以用相同的解题思路来解决。
为什么要递归 :解决一个大问题的时候会依赖到和大问题相同的小问题。问题类型一样,规模变小。
递归不能无限地进行下去,否则程序会陷入死循环。
递归的2个基本要素 :
① 递归公式:确定递归的方式,即原问题是如何分解为子问题的?
② 递归出口(边界):确定递归到何时终止,即递归的结束条件?
递归你只要记住要“早归”和算出正确的递归公式基本上就没什么问题了。