算法设计与分析之递归算法练习(下)

递归算法八:集合全排列问题

分析

当n=1时,
perm( R )=( r ),其中r是集合R中唯一的元素;
当n>1时,perm( R )由
(r1) perm(R1)
(r2) perm(R2)

(rn) perm(Rn)构成。

代码

void perm(int args[], int k, int m){
   if(k==m){
      for(int i=0;i<=m;i++)
         cout<<args[i]<<" ";
      cout<<endl;
   }
  else
    for(int j=k;j<=m;j++)  {
        swap(args[k],args[j]);
        perm(args,k+1,m);
        swap(args[k],args[j]);
   }
}

递归算法九:整数划分问题

分析

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

最大加数不超过6的分解方法数
=最大加数不超过5的分解方法数
+最大加数等于5的分解方法数
即q(6,6) = q(6,5) + q(0,6)
以此类推
在这里插入图片描述

代码

int integerDivision(int n,int m){
    if(n<1)
        return 0;
    else if(n==1||m==1)
        return 1;
    else if(n<m) return integerDivision(n,n);
    else if(n==m) return integerDivision(n,m-1)+1;
    return integerDivision(n,m-1)+integerDivision(n-m,m);
}

递归算法十:排队购票

问题描述

 一场球赛开始前,售票工作正在紧张进行中。
  每张球票为50元,
  有m+n个人排队等待购票,
  其中有m 个人手持50元的钞票,
  另外n个人手持100元的钞票。
 求出这m+n个人排队购票,使售票处不至出现找不开钱的局面的不同排队种数 。
(约定:开始售票时售票处没有零钱;拿同样面值钞票的人对换位置为同一种排队。)

分析

(1) n = 0,即所有人都拿50元的钞票,queueNum(m,n) = 1;
(2) m < n时,即使所有50元的钞票都找零也找不开,所以queueNum(m,n) = 0;
(3)
 1) 第m+n个人如果拿的100元钞票,那么总共的排队数量为queueNum(m,n-1);
 2) 第m+n个人如果拿的50元钞票,那么总共的排队数量为queueNum(m-1,n);
 综上,第三种情况的排队数:queueNum(m,n) = queueNum(m,n-1) + queueNum(m-1,n);

代码

int queueNum(int m, int n){
    if(n == 0) return 1;
    if(m < n) return 0;
    return queueNum(m-1,n) + queueNum(m,n-1);
}

递归算法十一:杨辉三角

分析

在这里插入图片描述
1、采用二维数组存储
2、对角线初始化为1,第一列初始化为1
3、其余情况yangHuiTriangle(i-1,j)+yangHuiTriangle(i-1,j-1);

代码

#include <iostream>

using namespace std;
const int N = 100;

int yangHuiTriangle(int i, int j);

int main()
{
    int n;
    cout<<"请输入杨辉三角的行数:";
    cin>>n;
    for(int i = 0;i < n;i++) {
        for(int j = 0;j <= i;j++)
            cout<<yangHuiTriangle(i,j)<<"\t";
        cout<<endl;
    }
    return 0;
}

int yangHuiTriangle(int i, int j){
    if(i == j) return 1;
    if(j == 0) return 1;
    return yangHuiTriangle(i-1,j) + yangHuiTriangle(i-1,j-1);
}

递归算法十二:计算两个数的最大公约数

分析

求最大公约数是个经典问题,我们这里介绍两种解决方法。
方法一:更相减损
  除非两数相等,否则两数中最大数和最小数的差值与最小数的公约数即为两数的公约数。
方法二:辗转相除
  除非两数求余为零,否则后数与前数对后数的取余值的公约数即为两数的公约数。

代码

//更相减损
int mcdMethod1(int num1,int num2){
    if(num1 == num2) return num1;
    else if(num1 > num2) return mcdMethod1(num1-num2,num2);
    else return mcdMethod1(num2-num1,num1);
}
//辗转相除
int mcdMethod2(int num1,int num2){
    if(num2) return mcdMethod2(num2,num1%num2);
    return num1;
}

递归算法十三:计算一个正整数中所有的数字之和

分析

除非正整数为零,否则整数除以十的结果与正整数取余十的和即为最后结果。

代码

int sumNum(int num){
    if(num) return sumNum(num/10) + num%10;
    return num;
}

递归算法十四:求(1+1/2+1/3+…+1/n)的和

分析

如果n = 1,返回1;否则返回sum(n-1) + 1.0/n。

代码

double sum(int n){
    if(n == 1) return 1;
    return sum(n-1) + 1.0/n;
}

本博客其他文章推荐

算法设计与分析之递归算法练习(上)

算法设计与分析之数字三角形问题

算法设计与分析之ZOJ2104- Let the Balloon Rise

算法设计与分析之优先队列及解决ZOJ1167

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值