递归详解

· · 个人记录

递归算法,归纳起来就有这几个特点。

  1. 它有一个基本部分,即直接满足条件,输出;
  2. 它有一个递归部分,即 通过改变基数(比如n),来逐步使得n满足基本部分的条件,从而输出;
  3. 它有一个超级弊端,即效率低(不过递归算法作为入门级算法还是很值得我这样的小白研究的。)。

几个经典问题:

  1. 全排列
  2. 阶乘
  3. hannoi(汉诺塔)

全排列

洛古 全排列问题

输出自然数1到n所有不重复的排列,即n的全排列,要求所产生的任一数字序列中不允许出现重复的数字。

一个数n(1≤n≤9)

由1~n组成的所有不重复的数字序列,每行一个序列。

3

代码:

#include<bits/stdc++.h> 
using namespace std;
int n;
int ans[15];//保存当前的方案
int use[15];//表示每个数是否被用过
void dfs(int x)//X表示当前搜索到那个数
{
    if(x > n)//如果N位都搜索完了,就输出方案并返回
    {
        for(int i = 1;i <= n;i++)
            cout<<ans[i];//输出方案 
        cout<<endl; 
        return;
    }
    for(int i = 1;i <= n;i++)//从小到大枚举
    if(!use[i])//判断这个数是否用过
    {
        ans[x] = i;//保存到方案中
        use[i] = 1;//标记这个数被使用了
        dfs(x + 1);//进行下一步搜索
        use[i] = 0;//撤销标记
    }
}
int main()
{
    cin>>n;//输入
    dfs(1);//从第一个数开始搜索;
    return 0; 
}

其实全排列还有一个STL的函数,瞬间AC: 哈哈哈

#include<bits/stdc++.h>
using namespace std;
int x[11];
int main()
{
    int n;
    cin>>n;
    for(register int i=1;i<=n;i++)//register 使循环更快; 
        x[i]=i,
        cout<<i;
    while(next_permutation(x+1,x+1+n))
    {
        cout<<endl;
        for(register int i=1;i<=n;i++)
            cout<<x[i]; 
    }
}

阶乘

一本通 阶乘问题

求10000以内n的阶乘。

N阶乘是由1到N相乘而产生

只有一行输入,整数n(0≤n≤10000)。

一行,即n!的值。

4

24

#include<bits/stdc++.h>// 万能头文件
#define ll long long//直接用ll代替long long
using namespace std;
ll jc(ll x)
{
    if(x == 1)
        return 1;
    return x * jc(x - 1);//每次乘比x小1的数,实现阶乘 
}
int main()//主函数,不多说 
{
    ll n;
    cin>>n;
    cout<<jc(n)<<endl;
    return 0;
}

不过要按照我这样写,超过26就不行了

hannoi(汉诺塔)

一本通 hannoi(汉诺塔)
此题有改动

输入为一个整数(小于20)后面跟三个单字符字符串。

整数为盘子的数目,后三个字符表示三个杆子的编号。

输出每一步移动盘子的记录。一次移动一行。

每次移动的记录为例如 a->3->b 的形式,即把编号为3的盘子从a杆移至b杆。

2 a b c

a->1->c a->2->b c->1->b

#include<bits/stdc++.h>
using namespace std;
int k=0;//统计步数 
void Hanoi(int n,char a,char b,char c)
{    
    if(n==0)//0的话,没什么好玩的了,直接退出!
        return ;
    else
    {        
        Hanoi(n-1,a,c,b);
        k++;
        printf("%d->%c->%c\n",k,a,c);
        Hanoi(n-1,b,a,c);
    }
}
int main()
{
    int n;
    cin>>n;
    Hanoi(n,'A','B','C');    
    return 0;
}

当然,如果只计算步数,还是有公式的:2^n-1

#include<bits/stdc++.h>
using namespace std;
int main()
{
    long long n;
    cin>>n;
    cout<<pow(2,n) - 1<<endl;
}