《编程简介(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. About Unixstickers - Unixstickers - stickers on unix, programming, software, development and open source

    About Unixstickers - Unixstickers - stickers on unix, programming, software, development and open so ...

  2. Installing SSL on CentOS | My Virtual Time Capsule

    Installing SSL on CentOS | My Virtual Time Capsule Installing SSL on CentOS Extracted from the Sourc ...

  3. poj1459(最大流)

    传送门:Power Network 题意:在一个网络图中有n个点,其中有np个发电站,nc个用户,m条电线;每个发电站,用户,和电线都对应有一个最大的电流;让求出该网络中最大的电流. 分析:最大流裸题 ...

  4. hdu2389(HK算法)

    传送门:Rain on your Parade 题意:t个单位时间后开始下雨,给你N个访客的位置(一维坐标平面内)和他的移动速度,再给M个雨伞的位置,问在下雨前最多有多少人能够拿到雨伞(两个人不共用一 ...

  5. C语言数组

    在C语言中,对于三维或三维以上数组的使用并没有很好的支持,而且使用率也非常的低,后面会对三维数组做一些简单的分析,这篇文章主要以二维数组来探讨一些C语言中数组使用的相关概念和技巧. 1 一个var[i ...

  6. red hat Linux 使用CentOS yum源更新

    red hat linux是商业版软件,没有经过注册是无法使用红帽 yum源更新软件的,使用CentOS源更新操作如下: 1.删除red hat linux 原有的yum 源 rpm -aq | gr ...

  7. BlueJ的code pad

    Java的REPL BlueJ的code pad实用吗?Java对(Read-Eval-Print Loop)不提供原生支持.这样的"交互式解释器"或"交互式编程环境&q ...

  8. 升级旧Delphi应用转向支持手机的一个思路

    系统架构改为B/S. 业务规则所有在服务端实现,使用REST服务封装旧有系统,这样可最大程度的利用原有代码. client所实用HTML5+javascript,这样client不须布署PC,可极大减 ...

  9. 解决方式:QSqlDatabase: an instance of QCoreApplication is required for loading driver plugins

    在用QSqlDatabase时遇到报错QSqlDatabase: an instance of QCoreApplication is required for loading driver plug ...

  10. .Net 内存溢出(System.OutOfMemoryException)

    .Net 内存溢出(System.OutOfMemoryException) 在什么情况下会出现OutOfMemonryException呢? 在我们试图新建一个对象时,而垃圾收集器又找不到任何可用内 ...