算法整理四——递归

目录

一、递归概述

一、求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

    算法整理四——递归_第1张图片

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

一、求n!

#include 

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<

二、斐波那契数列

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

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

#include 

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<

三、汉诺塔问题

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

用递归求的是如何移动?

#include 

using namespace std;



void move(char from,char to)

{

    cout<<"Move "<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 

using namespace std;



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

{

    if(n==10)

        return 1;

    else

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

}



int main(){

    cout<

五、十进制转换为二进制

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

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

#include 

using namespace std;



int change(int a,int radix)

{

    if(a!=0)

    {

        change(a/radix,radix);

        cout<>x>>radix;

    change(x,radix);

    cout<

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

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

#include 

using namespace std;



int change(int a)

{

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

    {

        cout<>x;

    change(x);

    cout<

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

#include 

using namespace std;



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

{

    if(k==m)

    {

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

            cout<

八、整数划分问题           

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

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

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

算法整理四——递归_第2张图片

分析:

整数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)

算法整理四——递归_第3张图片

#include

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

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

算法整理四——递归_第4张图片

#include

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<

大家都要加油啊!!!算法整理四——递归_第5张图片

你可能感兴趣的:(算法,c++,蓝桥杯)