《编程简介(Java) ·10.3递归思想》

10.3.1 递归的概念

以两种方式的人:男人和女人;算法是两种:递归迭代/通知;

递归方法用自己的较简单的情形定义自己

在数学和计算机科学中,递归是一种思路和策略,能够用于术语的定义(什么是表达式)问题的描写叙述问题求解。用于问题求解的递归称为递归法。

有一个故事。物理学家计算10!时会说。“看,它等于1*2*~*10,即3628800”;数学家则说:“哦。10的阶乘,它等于10乘以9。”。

递归算法“轻率地”觉得自己的较简单的情形是已知的。既然fact(n-1)是已知的,因而fact(n) 可求。

这样“轻率”对理解递归概念至关重要。递归法不直接解决这个问题,而是将问题变成一个趋向递归出口的问题。使用递归方法须要存在一个基准情形,以避免无限循环(狗追自己的尾巴)。

package algorithm.recursion;
public class RecursionDemo{
/**
* 递归求Fibonacci级数的第n个元素。n基于1的自然数。
*/
public static int fibonacc(int n){
if(n<=1) return n;
else return fibonacc(n-1)+fibonacc(n-2);
} /**
* 迭代求Fibonacci级数的第n个元素。n基于1的自然数。
*/
public static int fibonacc1(int n){
int first , second ,result ;
first =second=result= 1;
for(int i=3;i<=n ;i++){
result = first + second;
first = second;
second =result;
}
return result;
}
}

大多数情况下,迭代法和递归法可以相互转化。

使用递归法有2条实践准则:

1、设计优先。在不论什么情况下都能够採用递归法。简洁而清晰的程序设计优先。某些问题,比如那些须要后退的问题(如找出迷宫的出路、对树的一些操作)。假设不採用递归则非常难解决。

2、效率平衡

假设递归调用中出现反复性工作,改用循环。对于一般的数值计算,递归法通常不合适。

Java递归方法是通过方法调用栈实现的。在BlueJ中设置断点执行factorial (5),将显示方法调用情况。

它只“轻率地觉得”factorial (4)已知,依此类推。

到factorial (5),眼下没有进行任一乘法计算。方法调用栈中有6个栈帧,顶层将计算factorial (0)。递归的方法的两个阶段是递推和回归

比如使用递归式sum(n) =n + sum(n-1),yqj2065看见过一个趣题。

    static long sum1(long a) {
return (a == 1)? 1:(a + sum1(a - 1));
}
static long sum2(long a) {
return (a == 1)? 1:(sum2(a - 1) + a);
}

两者有差别吗?【注:在Java7时sum1(6000)StackOverflowError,Java8到大约13000才溢出。原因不明。】


10.3.2 汉诺塔

汉诺塔问题(Hanoi Tower problem):有三根杆子A、B、C,A杆上串有上小下大若干碟子。

每次移动一块碟子。在确保小碟子仅仅能叠在大碟子上面的条件下,利用B过渡,请把全部碟子从A杆移到C杆上。

对于具有递归思维的人。再多的碟子,也只是是两部分:上面的n-1个碟子被看成粘在一起的小碟子,而以下是一个大碟子。汉诺塔问题的递归算法:

结束条件: A杆上仅仅有一个碟子。将它移到C。

递归式:

1、将上面的n-1个碟子从出发地A移到中转站B;

2、将第n个碟子移到目的地C;

3、将n-1个碟子从中转站B移到目的地C。

package algorithm.recursion;
public class HanoiTower{
private static int step= 0;
/**汉诺塔的递归演示。
* @param from 碟子的出发地
* @param temp 碟子的中转站
* @param to 碟子的到达地
* @param n 要移动的碟子个数
*/
static void hanoi(char from, char temp, char to, int n){
if (n == 1) {
step++;
System.out.println("第"+step+ "步: "+ from+"→"+ to);
}else {
//将n-1个碟子移到中转站。故眼下的到达地是temp。
hanoi(from, to,temp,n-1);
//第n个碟子移到到达地
step++;
System.out.println("第"+step+ "步: "+ from+"→"+ to);
//将n-1个碟子移到到达地。
hanoi(temp,from,to,n-1);
}
}
}

hanoi(‘A’, ‘B’, ‘C’, 3)的输出:

第1步: A→C

第2步: A→B

第3步: C→B

第4步: A→C

第5步: B→A

第6步: B→C

第7步: A→C

汉诺塔问题的迭代算法比較复杂,代码库中有參考实现。

练习:

1.Given a non-negative int n, return the sum of its digits recursively (no loops). Note that mod (%) by 10 yields the rightmost digit (126 % 10 is 6), while divide (/) by 10 removes the rightmost digit (126 / 10 is 12).

sumDigits(126) → 9

sumDigits(49) → 13

sumDigits(12) → 3

类似的: 递归求一个非负int包括的5的个数。

2.小朋友排排坐,单号伸出2手指,双号伸出3手指,递归求n个小朋友时手指的总数。

sum(0) → 0

sum(1) → 2

sum(2) → 5

版权声明:本文博主原创文章,博客,未经同意不得转载。

《编程简介(Java) &#183;10.3递归思想》的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. CentOS上解压ZIP乱码的解决办法

    今天在学校做实验需要解压缩一些范例程序,我准备在我的电脑上把这个实验做完,所以就把文件copy到我的CentOS里面去了. 但是万万没想到``````解压缩的时候悲剧了,用unzip解压出来一大堆乱码 ...

  2. Hbase经常使用命令

    hbase shell命令的使用 再使用hbase 命令之前先检查一下hbase是否执行正常 hadoop@Master:/usr/hbase/bin$ jps 2640 HMaster 27170 ...

  3. POJ 2365 Rope(水题)

    [题意简述]:给出我们钉子个数与半径,让我们求出缠绕在钉子上的绳子有多长. [分析]:从题目中我们能够看出,绳子长度的和等于每两个钉子的距离的和加上接触在钉子上的绳子的长度,不难发现这部分长度事实上就 ...

  4. Nginx特点

    Nginx特点:1,跨平台:Nginx 能够在大多数 Unix like OS编译执行,并且也有Windows的移植版本号.2,配置异常简单:很easy上手.配置风格跟程序开发一样,神一般的配置.3, ...

  5. Android入门之简单短信发送器

    效果图: manifest.xml 文件中加入  <uses-permission android:name="android.permission.SEND_SMS"/&g ...

  6. AE+SceneControl源代码共享

    近来的,博友发私信或邮件交换,第一次使用前SceneControl代做一点project股票,做的很粗糙.我们希望对大家有帮助,欢迎留言交流哈萨克斯坦. 除了主开.保存.数据加载.询价,几个功能主要是 ...

  7. 六:Java之集合

    集合包括的内容非常多,我发现一个非常好的博客,感觉自己都没有写的必要了! 链接献上  Java集合

  8. robot framework 使用四:分层设计和截图以及注意事项

    再说一下眼下的主要环境信息和版本号: 操作系统:win7 64位 python版本号:2.7.6 RIDE版本号:1.2.3 selenium2library:1.5.0 selenium:2.40. ...

  9. Java 并发编程(三)为线程安全类中加入新的原子操作

    Java 类库中包括很多实用的"基础模块"类.通常,我们应该优先选择重用这些现有的类而不是创建新的类.:重用能减少开发工作量.开发风险(由于现有类都已经通过測试)以及维护成本.有时 ...

  10. JSP生成word文件

    1.jsp生成word文件,直接改动jsp格式: <%@ page contentType="application/vnd.ms-word;charset=GB2312"% ...