算法整理四——递归

目录

一、递归概述

一、求n!

二、斐波那契数列

三、汉诺塔问题

四、猴子摘桃问题

五、十进制转换为二进制

六、逆序(或正序)输出一个正数中的每一位数

七、集合的全排列【一点点不好理解】

八、整数划分问题           

九、递归求平方和函数(openjudge题目)


一、递归概述

(1)分治算法策略主要通过递归实现,大规模问题分解成小规模问题

可以理解为分治是一种算法思想,递归是实现这种思想的一种手段

  1. 分治法的设计思想:将一个难以直接解决的大问题,分解成一些规模较小的相同问题,以便各个击破,分而治之
  2. 直接或间接地调用自身的算法/函数称为递归算法/函数
  3. 用递归解决问题时,关键是确定递归体和递归出口

(2)掌握用递归方法解决问题:n!、菲波那契数列、汉诺塔问题、猴子摘桃问题、十进制转换为二进制、逆序(或正序)输出一个正数中的每一位数、集合的全排列、整数划分问题、递归求平方和函数(openjudge题目)

(3)递归程序的优点:

在计算机算法设计与分析中,使用递归技术往往使函数的定义和算法的描述简洁且易于理解

(4)递归程序的缺点:

递归算法解题的运行效率较低

在递归调用过程中,系统为每一层的返回点、局部变量等开辟了堆栈来存储。递归次数过多容易造成堆栈溢出等。

(5)解题思路:求n!

  • 递推:递推法的特点是从一个已知的事实(如1!=1)出发,按一定规律推出下一个事实(如2!=1!*2),再从这个新的已知的事实出发,再向下推出一个新的事实(3!=3*2!)。n!=n*(n-1)!。
  • 递归:即5!等于4!×5,而4!=3!×4…,1!=1

    

其实这样感觉的话递归、递推也没有太大的区别,那就从题目代码上来看一下区别吧。

一、求n!

#include <iostream>

using namespace std;



int fac(int n)//n>=0

{

    int f;

    if(n==0||n==1)

        f=1;

    else

        f=fac(n-1)*n;

    return f;

}

int main(){

    int n;//代表有几列

    cin>>n;

cout<<fac(n)<<endl;

}

二、斐波那契数列

用递推输出的是n个斐波那契数列

用递归输出的是第n个斐波那契数列是多少?

#include <iostream>

using namespace std;



int fib(int n)//n>=0

{

    int a;

    if(n==1||n==2)

        a=1;

    else

        a=fib(n-1)+fib(n-2);

    return a;

}



int main(){

    int n;//代表有几列

    cin>>n;

cout<<fib(n)<<endl;

}

三、汉诺塔问题

用递推求的是移动n个盘需要多少次?

用递归求的是如何移动?

#include <iostream>

using namespace std;



void move(char from,char to)

{

    cout<<"Move "<<from<<" to "<<to<<endl;

}



void hanoi(int n,char first,char second,char third)

{

    if(n==1)

        move(first,third);//递归出口

    else{

        hanoi(n-1,first,third,second);//A->B

        move(first,third);

        hanoi(n-1,second,first,third);//B->C

    }

}



int main(){

    int m;

    cout<<"小圆盘的个数为:";

    cin>>m;//m个小圆盘需要移动

hanoi(m,'A','B','C');

}

四、猴子摘桃问题

递推关系:f(n-1)=(f(n)+1)*2     边界条件:f(10)=1

递归·终止条件 n=10,返回1;

#include <iostream>

using namespace std;



int f(int n)//n>=0

{

    if(n==10)

        return 1;

    else

        return (f(n+1)+1)*2;

}



int main(){

    cout<<f(1)<<endl;

}

五、十进制转换为二进制

编写一个递归函数,将10进制转化成radix进制(输出二进制形式)

【除2求余,到商为0终止】

#include <iostream>

using namespace std;



int change(int a,int radix)

{

    if(a!=0)

    {

        change(a/radix,radix);

        cout<<a%radix;//输出余数

    }

}



int main(){

    int x,radix;

    //x是十进制数,radix是基数(转换为radix进制)

    cin>>x>>radix;

    change(x,radix);

    cout<<endl;

    return 0;

}

六、逆序(或正序)输出一个正数中的每一位数

例如,对于数12345,依次输出5 4 3 2 1

#include <iostream>

using namespace std;



int change(int a)

{

    if(a/10==0)//个位数

    {

        cout<<a;

    }

    else            //正序输出只需要交换这两句的位置即可;

    {

        cout<<a%10<<" ";//输出余数

        change(a/10);

    }

}



int main(){

    int x;

    cin>>x;

    change(x);

    cout<<endl;

    return 0;

}

七、集合的全排列【一点点不好理解】

#include <iostream>

using namespace std;



int Perm(int list[],int k,int m)

{

    if(k==m)

    {

        for(int i=0;i<=m;i++)

            cout<<list[i]<<" ";

        cout<<endl;

    }

    else

    {

        for(int j=k;j<=m;j++)

        {

            swap(list[k],list[j]);

            Perm(list,k+1,m);

            swap(list[k],list[j]);

        }

    }

}



int main(){

    int a[4]={1,2,3,4};//对集合a中的4个元素进行全排列

    Perm(a,0,3);//0代表第一个数是第几个位置,3代表最后一个数是第几个位置

    return 0;

}

八、整数划分问题           

将正整数n表示成一系列正整数之和:n=n1+n2+…+nk,

其中n1≥n2≥…≥nk≥1,k≥1。

正整数n的这种表示称为正整数n的划分。求正整数n的不同划分个数。

分析:

整数6的划分方法数 =最大加数等于6的划分方法数 +最大加数等于5的划分方法数 +最大加数等于4的划分方法数 +最大加数等于3的划分方法数 +最大加数等于2的划分方法数 +

最大加数等于1的划分方法数

即:

整数6的划分方法数 =最大加数等于6的划分方法数 +最大加数不大于5的划分方法数

或者

整数6的划分方法数 =最大加数不大于6的划分方法数

将n的最大加数不大于m的划分个数记作q(n,m)

  • n>m>1        q(n,m)=q(n,m-1)+q(n-m,m)
  • n=1||m=1     q(n,m)=1
  • m>n          q(n,m)=q(n,n)
  • m=n          q(n,m)=q(n,m-1)+q(n-m,m)

#include<iostream>

using namespace std;

int zshf(int n,int m){

    if(n<1)

        return 0;

    else if(n==1||m==1)

        return 1;

    else if(n<m)

        return zshf(n,n);

    else if(n==m)

        return zshf(n,n-1)+1;

    else

        return zshf(n,m-1)+zshf(n-m,m);

}

int main(){

    int n;

    n=zshf(6,3);//6的最大加数不大于3的划分个数

    cout<<n<<endl;

    return 0;

}

九、递归求平方和函数(openjudge题目)

#include<iostream>

using namespace std;

int f(int n)

{

    if(n==0||n==1)

        return n;

    else

        return n*n+f(n-1);



}

int main(){

    int n;

    cin>>n;

    cout<<f(n)<<endl;

}

大家都要加油啊!!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

季沐晴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值