递归的三个小题

(1)杨辉三角的那些事儿

以下为从度娘上复制的内容:

1

1 1

1 2 1

1 3 3 1

1 4 6 4 1

.。。。。。。。。

观察后可知:

1. 每行数值左右对称,且均为正整数。

2. 行数递增时,列数亦递增。

3. 除斜边上的1外,其余数值均等于其肩部两数之和。

杨辉三角与二项式定理有密切关系,即杨辉三角的第n行(n=0…MAX_ROW)对应二项式(a+b)n展开(Binomial Expansion)的系数集合。例如,第二行的数值1-2-1为幂指数为2的二项式(a+b)2展开形式a2 + 2ab + b2的系数,即。

应用组合公式可推导出杨辉三角的特征1和3,如下:

根据上面的有关组合数和二项式定理的内容,以及递推关系,利用递归的思想提供三个输出有限行杨辉三角的方法:

(i)直接使用C(r,n),设计思想很简单就是2层嵌套的for循环语句,利用组合数公式分别计算每个位置上的数字。当然组合数公式是直接多次调用提前写好的计算阶乘的方法来算。这个计算阶乘的方法就是利用了递归的操作。

简单的展示下递归的流程图吧,双循环的流程图没啥可画的。

(这个图很难说时正确的,只是个简单的流程图,基本上递归都是伪代码来表示)

 1 class PaTri1{
 2         public static BigInteger calculateN2(int n) {  //防止数据过大,用大整数表示
 3         if(n==1 || n==0){
 4             return BigInteger.valueOf(1);
 5         }
 6         return BigInteger.valueOf(n).multiply(calculateN2((n-1)));
 7     }
 8     public static void Ptriangle1(int row) {
 9         for(int i = 0;i<row;i++) {
10             for(int j = 0;j<=i;++j) {
11                 System.out.print(PaTri1.calculateN2(i).divide(PaTri1.calculateN2(j).multiply(PaTri1.calculateN2(i - j)))+" ");
12             }    //组合数公式,直接调用静态方法calculateN2()
13             System.out.println();
14         }
15     }
16 }

在主函数中直接调用PaTri1.Ptriangle1()这个静态方法即可

(ii)换个更加简单一点的方法,这次不用递归,用递推

即C(r,n) = C(r-1,n-1)+C(r,n-1)这个公式,不再使用那个阶乘的公式,直接从最顶上开始往下推,只不过要记录每个已经计算出来的值,以便后面的方便使用。

设计思路:还是那两层嵌套的for循环,自顶向下,从第一个位置算起,利用最上面那第三条规律,即该位置的数值等于它两肩上的两数之和(这里实在没必要再用那个组合数公式了),如果它上面只有一个数,剩下一个用0补。

 1 class PaTri2{
 2     private BigInteger[][]tmp;//用来记录已经计算了的值
 3     public BigInteger Cnr(int r,int n) {
 4         if(r<0)return BigInteger.valueOf(0);    //前两行就属于上面说的肩上为0的数
 5         else if(r > n)return BigInteger.valueOf(0);
 6         else return tmp[r][n];  //其他情况一定是有值存在的,因为是计算一个记录一个值,由于后面的数值计算要用到前面的值,而前面的值已经储存起来了,所以直接返回
 7     }
 8     public void Ptriangle2(int row) {
 9         tmp = new BigInteger[row][row];
10         tmp[0][0] = BigInteger.valueOf(1);
11         System.out.println(Cnr(0,0));
12         for(int i = 1;i<row;++i) {
13             for(int j = 0;j<=i;++j) {
14                 tmp[j][i] = Cnr(j-1,i-1).add(Cnr(j,i-1));//连续地调用,不会发生递归,一次出结果
15                 System.out.print(tmp[j][i]+" ");
16             }
17             System.out.println();
18         }
19     }

使用这个类需要定义对象,通过对象实例调用成员方法传值进行指定行杨辉三角的输出

(iii)换种递归方式来写,第一种方法的递归体现在具体的每个位置数值的计算上,第二种和递归无关是多次利用递推公式来自顶向下计算。这种方法则和第二种方法完全相反,是自底向上的递归,从最后一行第一个位置开始(只计算最后一行),每一个数字都需要它肩上两个数字,返回这些数字值的是一个方法,由此通过递归的调用这些方法来完成上面的数字的计算,看似是先从最后往上,实则是还是先计算最前面的,依次往后带入前面已知的结果进行计算。

 1 class PaTri3{
 2     private BigInteger[][]crn;        //用来记录每个已经计算出来的位置上的数值
 3     public BigInteger Cnr(int r,int n) {
 4         if(r == 0&&n == 0) {     //最顶上的出口
 5             crn[r][n] = BigInteger.valueOf(1);
 6             return BigInteger.valueOf(1);
 7         }
 8         else if(r <0)return BigInteger.valueOf(0); //越界的应该为0的值,有些边界上的数肩上只有一个数字,另一个不存在的用0来替代,这里就是为那些肩上只有一个数的位置的计算是发生的调用作准备
 9         else if(r > n)return BigInteger.valueOf(0); //同上
10         else {
11             crn[r][n] = Cnr(r-1,n-1).add(Cnr(r,n-1));  //利用了递推公式进行递归调用,并将结果保留在相应的位置上
12             return crn[r][n];
13         }
14     }
15     public void Ptriangle3(int row) {
16         crn = new BigInteger[row][row];
17         for(int j = 0;j<=row - 1;j++)
18                 Cnr(j,row - 1);     //直接计算最后一排位置上的数字,间接通过该函数内部的递归计算所有位置上的数字
19         for(int i = 0;i<row;++i) {         //用双层for循环打印保存的结果
20             for(int j = 0;j<=i;++j)
21                 System.out.print(crn[j][i]+" ");
22             System.out.println();         //分行输出
23         }
24     }
25 }

(这个类写的比较差,不能在计算的同时输出相应位置上的计算结果,而且很多位置会重复计算。在每个位置上可以设置相应的标记值,标记值正确则直接取已经保存了的计算结果,标记值错误则调用方法计算,但是这样会额外占据很多空间,还有就是可以只计算每行前一半位置上的不重复的数字,在输出时对循环条件加以限制可以将剩下那一半重复了的输出出来。这两个思路都能在一定程度上解决计算步骤过多的问题:前一种能完全解决重复计算的问题,后一种只是减少了近一半的运算量,剩下的一半还需要进行和前一种思路相同的操作才能取消重复的运算)使用时同样需要定义对象实例,通过具体的对象实例调用成员方法。

插张验证的截图:

(2)汉诺塔

汉诺塔是个古老的问题,就是A柱上串着从大到小一次摆放的盘子,这摞盘子以相同的形式摆放在另一个C柱上,一次只能移动一个盘子,且在放置盘子的过程中大盘在下小盘在上,有一个空的B柱做过度,来回移动盘子的问题,让你给出移动的步骤。

这个问题可以递归也可以不递归,这里就写下递归解决的思路。首先要有方法move(char a,char b),表示从柱子a移动到柱子b的过程。其次就是Hanoi(int num,char a,char b,char c)方法的完成,问题的解决就是重复递归调用这个Hanoi方法。我们要清楚,当只有一个盘子的时候,直接把这个盘子从a移动到c即可,也就是num = 1时,直接执行move(a,c);不过当有两个盘子的时候,要先将小盘子放到b上,然后就是只有一个盘子的情况了,也就是把最后一个盘子直接从a移动到c,最后再将b上的盘子移动到c即可;但是有三个盘子或者以上的时候情况会复杂一些,你需要把除了最底下那个最大盘子外所有的盘子看成一个盘子,把这一整个盘子先移动到c柱。一下子就移动到b显然不可能,不过你会发现,这个时候c柱子是空的,也就是说把n个盘子以b为过度从a移动到c的过程其实和把n - 1个盘子以c为过度从a移动到b是同一个过程,这就是递归的来源了,问题的子问题需要和原来问题一样的解决方式,只是再规模上缩小了一些。回头再看两个盘子的情况,将上面小盘子从a移动到b也是这么个步骤,故n>=2时,都是需要把n-1个盘子以c为过度从a移动到b的过程的(注:这里也要注意三个柱子的角色问题,初始状态下a柱是起始柱,c柱是目标柱,空着的b柱是一个辅助的柱子,但是再移动过程中这三个柱子的角色会变化,比如第二部移动那n - 1个盘子的时候,整个过程是以a柱是起始柱,b柱是目标柱,空着的c柱才是用来辅助移动的柱子,等到了n-1的子问题n-2时,三个柱子的角色又不相同了,所以不能被已经固定的a,b,c三个柱子迷惑,因为他们的角色在解决问题的不同阶段不一定是一样的,直接点讲,在调用Hanoi过程中重要的是传入a,b,c的顺序)。现在假设n - 1个盘子已经按要求移动到b柱上了,直接将剩下的最大盘子从a移动到c即可,最后,还是一样的操作,以空着的a柱作为辅助移动的柱子,将放在b上的n - 1盘子移动到c柱上。画成流程图很简单

源码比较简单:

 1 public class Hanoi {
 2       public static int round = 0;
 3       public static void move(char a,char b) {
 4           System.out.println("第"+(++round)+"步:"+a+"----->"+b);
 5       }
 6       public static void hanoi(int num,char a,char b,char c) {
 7           if(num<=0) {
 8               System.out.println("不能进行汉诺塔游戏!");
 9               return;
10           }
11           if(num == 1)move(a,c);
12           else {
13               hanoi(num - 1,a,c,b);
14               move(a,c);
15               hanoi(num - 1,b,c,a);
16           }
17       }
18       public static void main(String[]args) {
19           Scanner s = new Scanner(System.in);
20           System.out.print("输入盘子的个数:");
21           int num = s.nextInt();
22           s.close();
23           System.out.println("开始步骤分解:");
24           Hanoi.hanoi(num, 'A', 'B', 'C');
25           return;
26       }
27 }

(3)回文

不多介绍了,直接上思路:判断一个字符串是不是回文,首先要看他的第一个和最后一个字符是否相同,不相同直接pass掉,相同则缩短该字符串检索范围,忽略首位字符后看新的首尾字符是否相同,以此类推。很明显的能看出递归。递归的出口有两个:当字符串长度为基数时,递归到最后只有一个字符;当字符串长度为偶数时,递归到最后有相邻的两个字符,如果这两个字符相同则是回文。

流程图:

源代码:

 1 public class Palindrome {
 2       public static void isPal(String str,int low,int high) {
 3           if(low==high) {
 4               System.out.println(str+"是回文");
 5               return;
 6           }
 7           if(low == high - 1) {
 8               if(str.charAt(low)==str.charAt(high)) {
 9                   System.out.println(str+"是回文");
10                   return;
11               }
12               else {
13                   System.out.println(str+"不是回文");
14                   return;
15               }
16           }
17           if(low == high - 2) {
18               if(str.charAt(low)==str.charAt(high)) {
19                   System.out.println(str+"是回文");
20                   return;
21               }
22               else {
23                   System.out.println(str+"不是回文");
24                   return;
25               }
26           }
27           if(low<high&&high-low>2) {
28               if(str.charAt(low)==str.charAt(high))isPal(str,low+1,high-1);
29               else {
30                   System.out.println(str+"不是回文");
31                   return;
32               }
33           }
34       }
35       public static void main(String[]args) {
36              System.out.print("输入一个字符串:");
37              Scanner s = new Scanner(System.in);
38              String str = "";
39              str = s.next();
40              s.close();
41              Palindrome.isPal(str,0,str.length()-1);
42       }
43 }

转载于:https://www.cnblogs.com/messi2017/p/7658161.html

课程作业----递归那些事相关推荐

  1. 兰州大学C语言程序设计课程作业,【兰州大学|兰州大学C语言程序设计课程作业( 五 )】语言程序设计|课程|作业-傻大方...

    『易坊知识库摘要_兰州大学|兰州大学C语言程序设计课程作业( 五 )』34.用户未作答标准答案exp04. 以下叙述中正确的是 在程序的一行上可以出现多个有效的预处理命令行使用带参的宏时,参数的类型应 ...

  2. 兰州大学C语言程序设计课程作业,兰州大学C语言程序设计课程作业1附答案.doc...

    兰州大学C语言程序设计课程作业1附答案.doc C 语言程序设计课程作业语言程序设计课程作业_A 历次成绩 完成时间 查看详情 1.0.0 2015-11-21 091531 2.0.0 2015-1 ...

  3. 编译原理课程作业-Cminus语言的词法及语法分析器实现

    Cminus Compiler 编译原理课程作业-Cminus语言的词法及语法分析器实现 设计思想 词法分析 使用确定有限态自动机(DFA)实现与Lex自动分析两种方式实现. 语法分析 使用递归下降方 ...

  4. 第一次软件工程课程作业

    第一次的软件工程课程作业 这个作业属于哪个课程 <18级软件工程基础> 这个作业要求在哪里 我在这个课程的目标是 能熟练的运用编程知识,具备个人基本开发能力 这个作业在哪个具体方面帮助我实 ...

  5. 机器学习与数据挖掘 课程作业 基于数据驱动的空调结霜程度检测方法研究

    机器学习与数据挖掘 课程作业 基于数据驱动的空调结霜程度检测方法研究 摘要: 在我国的夏热冬冷地区,由于没有集中供暖,在冬季使用空调制热进行供暖是一种很常见的方式,但该地区冬季空气相对湿度较高并且环境 ...

  6. 有关我零基础入门Opengl并想开发七巧板小程序交作业这档子事

    有关我零基础入门Opengl并想开发七巧板小程序交作业这档子事 隔壁笔记链接:入手OpenGL 隔壁技术实现链接:部分思路实现 背景故事 c++课程老师给布置作业,"小作业",使用 ...

  7. 全球名校课程作业分享系列(7)--斯坦福计算机视觉与深度学习CS231n之基于cifar10的卷积神经网络实践

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/yaoqiang2011/article ...

  8. 大学计算机作业查重,大学生课程作业进行查重?别把“水论文”之过都抛给学生!...

    让一个本科生写出高水平,不重复的论文,不现实,"水论文"这一现象不能全怪学生!(水论文即由学生或由他人代学生撰写的质量水平较低的论文.) 日前,教育部印发<关于狠抓新时代全国 ...

  9. 全球名校课程作业分享系列(5)--斯坦福计算机视觉与深度学习CS231n之特征抽取与图像分类提升

    课程作业原地址:CS231n Assignment 1 作业及整理:@邓妍蕾 && @Molly && @寒小阳 时间:2018年1月. 出处:http://blog. ...

  10. 2017《面向对象程序设计》课程作业八

    1.时间匆匆,本学期的博客作业就要结束了,是否有点不舍,是否还想继续迭代优化你们计算器项目的作业呢?本学期最后一次博客作业,请大家描述: 从寒假到这次结束,经历的博客及编码作业的过程; 寒假在半年以前 ...

最新文章

  1. js获取被点击的元素以及子元素
  2. 如何运用领域驱动设计 - 领域事件
  3. python怎么让py里面逐行运行_怎样在安卓上运行python
  4. 2022年茶艺师(初级)上岗证题库及在线模拟考试
  5. 判断日期是否是明天,今天,昨天
  6. 牛客网刷题java之变态跳台阶一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
  7. thinkadmin V6 Experiences
  8. 如何将文字转化为语音?方法超级简单,立马就能学会配音
  9. Unity android平台读取文件
  10. python基于svm实现指数预测_基于SVM的股票预测 Python实现 附Github
  11. Gym 100971A Treasure Island
  12. 大国重器“兵器谱”,了解一下
  13. HX=JE,HX-JE芯片,无感升压ic
  14. 解决Eclipse不出提示
  15. C#调用TSC条码打印机打印条码
  16. [实验室每日一题][20201124][Zip已知明文攻击]
  17. Allegro测量距离如何同时显示mil和mm双单位
  18. Movist Pro for mac如何同时查看多个字幕?
  19. 遗世蒹葭~小甲鱼~数据结构和算法_02~线性表
  20. Linux中查看进程的虚拟地址空间内存布局

热门文章

  1. BigDecimal 加减乘除
  2. 设计模式-工厂模式(二)
  3. (转)正则表达之零宽断言(零宽度正预测先行断言)
  4. 北漂周记--第5记--拼命编程
  5. 学术论文-结果描述常用表达
  6. crontab的使用记录
  7. 仿微信朋友圈图片按下效果
  8. 和 Pipelining 说再见,cURL 放弃使用管道技术
  9. 关于SSMS显示select出来的数据行的疑问
  10. main方法中调用spring注入bean