2019年2月4日训练日记(递归学习小结)

今天简单写一下有关递归方面的小结:

递归

概念:当函数的定义中,其内部操作又直接或间接的出现对自身的调用,则这样的程序嵌套为递归定义。
函数直接调用其自身,称为直接递归,间接调用其自身,称之为间接递归

能够用递归算法解决的问题,一般满足如下要求

一、需要求解的问题可以转化为子问题求解,其子问题的求解方法与原问题相同,只是规模上的增大或减小。
二、递归调用的次数是有限的;必须有递归结束的条件(称为递归边界)。

递归应用举例:
一、求两个数的最大公约数,可以用枚举因子的方法,从两者中较小的数字枚举到能被两个数同时整除且是最大公约数的方法;也可以用辗转相除法,这里采用递归实现辗转相除算法。
方法一:

#include<iostream>
using namespace std;
int gcd(int ,int );
int main()
{
    int m,n;
    cin>>m>>n;
    cout<<"gcd="<<gcd(m,n)<<endl;
    return 0;
}
int gcd(int m,int n)
{
    return n==0?m:gcd(n,m%n);
}

方法二:
二进制最大公约数算法

#include<iostream>
using namespace std;
int gcd(int m,int n)
{
    if(m==n)return m;
    if(m<n)return gcd(n,m);
    if(m%2==0)
    {
        if(n%2==0)return 2*gcd(m/2,n/2);
            else return gcd(m/2,n);
    }
    else
    {
        if(n%2==0)return gcd(m,n/2);
        else return gcd(n,m-n);
    }
}
int main()
{
    int m,n;
    cin>>m>>n;
    cout<<gcd(m,n)<<endl;
    return 0;
}

此程序递归终止条件:gcd(m,m)=m.
递归关系式:m<n时:gcd(m,n)=gcd(n,m)
m为偶数,n为偶数:gcd(m,n)=2*gcd(m/2,n/2)
m为偶数,n为奇数:gcd(m,n)=gcd(m/2,n)
m为奇数,n为偶数:gcd(m,n)=gcd(m,n/2)
m为奇数,n为奇数:gcd(m,n)=gcd(n,m-n)
该方法和方法一相比更适合求高精度数的最大公约数,因为只涉及除2和减法操作,而辗转相除法则需要用到高精度除法。
这种求最大公约数的方法也是第一次涉及到。

二、已知一个一维数组a1…n,又已知一整数m。如能使数组a中任意几个元素之和等于m,则输出YES,反之输出NO。
采用全局变量编写程序如下:

#include<iostream>
using namespace std;
const int max1=51;
int a[max1],n,m;
bool flag;
void sum(int ,int );
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
        cin>>m;
    flag=false;
    sum(n,m);
    if(flag)cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
    return 0;
}
void sum(int n,int m)
{
    if(a[n]==m)flag=true;
    else if(n==1)return;
    else
    {
        sum(n-1,m-a[n]);
        sum(n-1,m);
    }
}

其实这个程序我总是感觉会超时或者超内存,不过还好,题目给的n<25,数据数量有限且不算太多,但是如果没有这个限制...数据过多过大时总觉得这个程序会出现问题。

原文地址:https://www.cnblogs.com/study-hard-forever/p/12130065.html