递归算法

发布时间 2023-07-20 16:59:14作者: 郁佳彬

 一、基本概念

            递归算法是一种直接或者间接调用自身函数或者方法的算法。递归算法的实质是把问题分解成规模缩小的同类问题的子问题,然后递归调用方法来表示问题的解。递归算法对解决一大类问题很有效,它可以使算法简洁和易于理解。递归算法,其实说白了,就是程序的自身调用。我们可以利用大道至简的思想,把一个大的复杂的问题层层转换为一个小的和原问题相似的问题来求解。递归往往能给我们带来非常简洁非常直观的代码形势,从而使我们的编码大大简化,然而递归的思维确实很我们的常规思维相逆的,我们通常都是从上而下的思维问题, 而递归趋势从下往上的进行思维。这样我们就能看到我们会用很少的语句解决了非常大的问题,所以递归策略的最主要体现就是小的代码量解决了非常复杂的问题。

   递归算法解决问题的特点:
   1)递归就是方法里调用自身。
   2)在使用递增归策略时,必须有一个明确的递归结束条件,称为递归出口。
   3)递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。所以一般不提倡用递归算法设计程序。
   4)在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等,所以一般不提倡用递归算法设计程序。

   在做递归算法的时候,一定要把握住出口,也就是做递归算法必须要有一个明确的递归结束条件。这一点是非常重要的。其实这个出口是非常好理解的,就是一个条件,当满足了这个条件的时候我们就不再递归了。

二、程序示例

1.斐波那契数列

【题目描述】

菲波那契数列是指这样的数列: 数列的第一个和第二个数都为1,接下来每个数都等于前面2个数之和。

给出一个正整数a,要求菲波那契数列中第a个数是多少。

【输入】

第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数a(1<=a<=20)。

【输出】

输出有n行,每行输出对应一个输入。输出应是一个正整数,为菲波那契数列中第a个数的大小。

【输入样例】

4
5
2
19
1

【输出样例】

5
1
4181
1

【个人代码(c++)】

#include<bits/stdc++.h>
using namespace std;

int a[20],b[10000];
int main()
{
int n,max=0;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>b[i];
if(max<b[i]) max=b[i];
}
a[1]=1;a[2]=1;
for(int i=3;i<=max;i++){
a[i]=a[i-1]+a[i-2];
}
for(int i=1;i<=n;i++){
cout<<a[b[i]]<<endl;
}
return 0;
}

2.阶乘问题

【题目描述】

数学上用 n! 表示阶乘,表示 1*2*3*...*n。
请你编程求1*2*3*...*n。

【输入】

输入一行,只有一个整数n(1<=n<=10)。

【输出】

输出只有1个整数。

【输入样例】

5

【输出样例】

120

【个人代码(c++)】

#include<bits/stdc++.h>
using namespace std;

int main()
{
int n,a=1;
long long b;
cin>>n;
for(int i=1;i<=n;i++){
b=a*i;
a=b;
}
cout<<b;
return 0;
}

3.集合的划分

【题目描述】

设S是一个具有n个元素的集合,Sa1a2an,现将S划分成k个满足下列条件的子集合S1S2Sk,且满足:

1.Si≠0

2.SiSj=0        (1ijkij)

3.S1S2S3SkS

则称S1S2Sk是集合S的一个划分。它相当于把S集合中的n个元素a1a2an 放入k个(0kn30)无标号的盒子中,使得没有一个盒子为空。请你确定n个元素a1a2an放入k个无标号盒子中去的划分数S(n,k)

【输入】

给出nk

【输出】

n个元素a1a2an 放入k个无标号盒子中去的划分数S(n,k)

【输入样例】

10 6

【输出样例】

22827
【个人代码(c++)】

#include<bits/stdc++.h>
using namespace std;

int long long s(int n,int k)
{
if(k==1||k==n){
return 1;
}else{
if(k==0||(k>n)){
return 0;
}else{
return s(n-1,k-1)+k*s(n-1,k);
}
}
}
int main()
{
int n,k;
cin>>n>>k;
cout<<s(n,k);
}

(代码带有个人理解,仅供参考)

经典例题还有汉诺塔问题、最大公约数问题等,本人不再具体列举,读者可自行探究。