递归

1、一个楼梯有20级,每次走1级或是2级,从底走到顶一共有多少中走法?
算法:
    设 n 是阶数,f(n) 是上 n 阶的不同走法数,则第一步可以走一阶或者是两阶,
    那么这三种情况下剩余的阶数分别为 n-1、n-2,
    所以 f(n) = f(n-1) + f(n-2)。

//递归解法

int solution1(int n)

{

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

    else return solution1(n-1) + solution1(n-2);

}

 

//非递归解法

int f[100];

int solution2(int n)

{

    f[0] = 1;

    f[1] = 1;

    for(int i=2; i<=n; ++i)

      f[i] = f[i-1] + f[i-2];

    return f[n];

}

2、质因数分解:得到num的所有质因数

void prime_number(int num, int n)

{

    if(num > n)

    {

        while(num % n) n++; //找到一个质因数

        num /= n; //除以这个质因数

        cout<<n<<endl; //打印这个质因数

        prime_number(num,n);

    }

}

int main()

{

    int n = 1001;

    prime_number(n,2);

    return 0;

}

3、不用任何中间变量,如何获取字符串的长度

int my_strlen(const char* str)

{

    if(*str == '\0') return 0;

    else return my_strlen(str+1)+1;

}

不用任何中间变量,以递归反序输出一个字符串:

void reverse(const char *p)

{

    if(*p == '\0') return;

    reverse(p+1);

    printf("%c",*p);

}

4、全排列和全组合

#include <iostream>

using namespace std;

 

template <class Type>

void permute(Type a[], int start, int end)

{

    if(start == end)

    {

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

        {

            cout<<a[i]<<" ";

        }

        cout<<endl;

    }

    else

    {

        for(int i = start; i <= end; ++i)

        {

            swap(a[i],a[start]);

            permute(a,start+1,end);

            swap(a[i],a[start]);

        }

    }

}

 

template <class Type>

void combine(Type a[], bool b[], int start, int end)

{

    if(start > end)

    {

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

        {

            if(b[i])

                cout<<a[i]<<" ";

        }

        cout<<endl;

    }

    else

    {

        b[start] = true;

        combine(a,b,start+1,end);

        b[start] = false;

        combine(a,b,start+1,end);

    }

}

 

int main()

{

    int p[3]={1,2,3};

    int N = 3;

    cout<<"permute:"<<endl;

    permute(p,0,N-1);

    cout<<"combine:"<<endl;

    bool b[3];

    combine(p,b,0,N-1);

 

    return 0;

}

全组合还有一个有趣的解法:可以构照一个长度为n(字符串的长度)的01字符串(或二进制数)表示输出结果中最否包含某个字符,比如:对于字符串“abc”,"001"表示输出结果中不含字符a、b,只含c,即输出结果为c,而"101",表示输出结果为ac。原题就是要求输出"001"到"111"这2^n–1个组合对应的字符串。
参考:http://www.cnblogs.com/luxiaoxun/archive/2012/08/08/2628153.html

5、给出一个集合,如{1, 2, 3, 4},打印出该集合的所有子集 分析一下问题,子集是指取原集合中的任意多个元素,转化一下问题,就是对于原集合中的任何一个元素,都有两个选择,包含或者不包含,所以对于n个元素的集合,其子集数为:2*2*2...= 2^n,去掉空集就是2^n-1个。那么可以得出其递归算法,本题实质上和打印字符串的所有组合是一样的。

void Recursive_Subsets(int* a, bool* b, int start, int end)

{

    if(start <= end)

    {

        b[start] = true; // pick thea[start]

        Recursive_Subsets(a, b, start+1, end);

 

        b[start] = false; // not pickthe a[start]

        Recursive_Subsets(a, b, start+1, end);

    }

    else

    {

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

        {

            if (b[i]) cout << a[i];

        }

        cout << endl;

    }

}

 

void PrintAllSubsets(int* a, int n)

{

    bool* b = new bool[n];

    Recursive_Subsets(a, b, 0, n-1);

    delete b;

}

6、电话号码对应的字符组合

题目:在电话或者手机上,一个数字如2对应着字母ABC,7对应着PQRS。那么数字串27所对应的字符的可能组合就有3*4=12种(如AP,BR等)。现在输入一个3到11位长的电话号码,请打印出这个电话号码所对应的字符的所有可能组合和组合数。

#include<iostream>

using namespace std;

 

const char* letter[10]={"","","ABC","DEF","GHI","JKL","MNO","PQRS","TUV","WXYZ"};

const int num[10]={0,0,3,3,3,3,3,4,3,4};

char input[20];

char output[20];

 

void solve(int p,int len)

{

    if(p == len)

    {

        output[len] = '\0';

        cout<<output<<endl;

        return;

    }

    int i;

    for(i=0; i<num[input[p]]; i++)

    {

        output[p] = letter[input[p]][i];

        solve(p+1,len);

    }

}

 

int main()

{

    scanf("%s",input);

    len = strlen(input);

   

    int total = 1;

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

    {

        input[i] -= '0';

        total *= num[input[i]];

    }

    solve(0,len);

 

    cout<<"The total num of combination is "<<total<<endl;

    return 0;

}

7、CoinChagne:硬币找零问题

硬币找零问题:给定一个正整数N,和一个正整数集合S,集合中的每个元素都有无限个,如何选定集合中的元素组合使其和为N For example, for N= 4, S = {1,2,3}, there are four solutions: {1,1,1,1},{1,1,2},{2,2},{1,3}.

递归解法:假设集合S中的元素的顺序是递增的,则: C(N,M),表示从M个元素选中若干个满足和为N的解法个数,则C(N,M)=C(N,M-1)+C(N-S[M-1],M-1)
C(N,M)=1, N=0
C(N,M)=0, N<0
C(N,M)=0, N>=1,M<=0

int Count(int N, int *s, int M)

{

    if(N == 0) return 1;

    if(N < 0) return 0;

    if(N >= 1 && M <= 0) return 0;

    return Count(N,s,M-1)+Count(N-s[M-1],s,M-1);

}

最少硬币找零问题:给定一个正整数N,和一个正整数集合S,集合中的每个元素都有无限个,如何选定最少的集合中元素,使其和为N For example, for N= 4, S = {1,2,3}, there are two solutions: {2,2},{1,3}.

递归解法:假设集合S中的元素的顺序是递增的,C(N,M),表示从M个元素选中若干个满足和为N的解法个数,则: C(N,M)=min(C(N,M-1),C(N-S[M-1],M-1))+1

int minCount(int N, int *s, int M)

{

    if(N == 0) return 1;

    if(N < 0) return 0;

    if(N >= 1 && M <= 0) return 0;

    return min(Count(N,s,M-1),Count(N-s[M-1],s,M-1))+1;

}

8、输入两个整数 n 和 m,从数列1,2,3...n中随意取几个数,使其和等于m ,要求将其中所有的可能组合列出来。

解为:此题等同于整数分解问题,将m分解成n以内的解为:f(n,m),分解成两个子问题:f(n-1,m-n)和f(n-1,m)

vector<int> vec;

void find_factor(int sum, int n)

{

    if(n <= 0 || sum <= 0)

        return;

    if(sum == n)

    {

        for(vector<int>::iterator iter = vec.begin(); iter !=vec.end(); iter++)

            cout << *iter << " + ";

        cout << n << endl;

    }

    vec.push_back(n);

    find_factor(sum-n, n-1);   //nn-1个数填满sum-n

    vec.pop_back();

    find_factor(sum, n-1);     //不放nn-1个数填满sum

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值