《编程简介(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. vijos P1352 最大获利(最小割)

    请不要随便指点别人该怎么做.每一个人的人生都应该自己掌握.你给不了别人一切.你也不懂别人的忧伤. 微笑不代表快乐.哭泣不一定悲伤 不努力怎么让关心你的人幸福.不努力怎么让看不起你的人绝望. 我用生命在 ...

  2. Android开发之使用URL訪问网络资源

    Android开发之使用URL訪问网络资源 URL (UniformResource Locator)对象代表统一资源定位器,它是指向互联网"资源"的指针. 资源能够是简单的文件或 ...

  3. Enum实现单例模式

    package com.wjy.effective; public enum Singleton { INSTANCE; private int numa; private int numb; pub ...

  4. ASPF简介

    ASPF是一种应用层状态检测技术,它通过与NAT和ALG等技术的组合应用,实现对应用层协议状态的处理和检测. 1.1  产生背景 随着计算机技术和网络技术的普及,网络安全问题也越来越得到关注.防火墙作 ...

  5. C#文件流写入方法

    stream为服务端接收的文件流 var bytes = new byte[stream.Length]; stream.Read(bytes, 0, bytes.Length); // 设置当前流的 ...

  6. 【译】ASP.NET MVC 5 教程 - 3:添加视图

    原文:[译]ASP.NET MVC 5 教程 - 3:添加视图 在本节内容中,我们将修改HelloWorldController类,使用视图模板来干净利索的封装生成HTML响应客户端的过程. 您将创建 ...

  7. cocoa动态方法决议及消息转发

    假设给一个对象发送不能响应的消息,同一时候又没有进行动态方法决议,又没实现消息转发,那么就会引发以下的crash信息 2014-07-30 15:47:54.434 MethodNotFind[171 ...

  8. 关于split与StringTokenizer的理解

    关于split与StringTokenizer的理解 一.split    依据匹配给定的正則表達式来拆分此字符串.此方法返回的数组包括此字符串的子字符串,每一个子字符串都由还有一个匹配给定表达式的子 ...

  9. apache +php +php curl 模块设置

    2.2 linux 下面 2.2.1 web服务器安装 1目前采用的web服务器是apache2,在ubuntu 下安装 apt-getupdate apt-get installapache2 测试 ...

  10. Android - 位置定位(Location)服务(Service)类的基本操作

    位置定位(Location)服务(Service)类的基本操作 本文地址: http://blog.csdn.net/caroline_wendy 定位服务(Location Service),能够确 ...