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

简介:

《编程简介(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


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





本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4869075.html,如需转载请自行联系原作者


相关文章
|
13天前
|
安全 算法 Java
深入理解Java并发编程:线程安全与性能优化
【4月更文挑战第11天】 在Java中,高效的并发编程是提升应用性能和响应能力的关键。本文将探讨Java并发的核心概念,包括线程安全、锁机制、线程池以及并发集合等,同时提供实用的编程技巧和最佳实践,帮助开发者在保证线程安全的前提下,优化程序性能。我们将通过分析常见的并发问题,如竞态条件、死锁,以及如何利用现代Java并发工具来避免这些问题,从而构建更加健壮和高效的多线程应用程序。
|
1天前
|
Java API 调度
[Java并发基础]多进程编程
[Java并发基础]多进程编程
|
1天前
|
Java API 调度
[AIGC] 深入理解Java并发编程:从入门到进阶
[AIGC] 深入理解Java并发编程:从入门到进阶
|
1天前
|
前端开发 Java 测试技术
Java从入门到精通:4.1.1参与实际项目,锻炼编程与问题解决能力
Java从入门到精通:4.1.1参与实际项目,锻炼编程与问题解决能力
|
1天前
|
SQL Java 数据库连接
Java从入门到精通:2.3.2数据库编程——了解SQL语言,编写基本查询语句
Java从入门到精通:2.3.2数据库编程——了解SQL语言,编写基本查询语句
|
1天前
|
SQL Java 数据库连接
Java从入门到精通:2.3.1数据库编程——学习JDBC技术,掌握Java与数据库的交互
ava从入门到精通:2.3.1数据库编程——学习JDBC技术,掌握Java与数据库的交互
|
1天前
|
IDE Java 开发工具
Java从入门到精通:1.3.1实践编程巩固基础知识
Java从入门到精通:1.3.1实践编程巩固基础知识
|
4天前
|
并行计算 Java 编译器
Java Lambda表达式简介
Java Lambda表达式简介
11 0
|
5天前
|
IDE Java 物联网
《Java 简易速速上手小册》第1章:Java 编程基础(2024 最新版)
《Java 简易速速上手小册》第1章:Java 编程基础(2024 最新版)
13 0
|
6天前
|
安全 Java 开发者
Java并发编程:深入理解Synchronized关键字
【4月更文挑战第19天】 在Java多线程编程中,为了确保数据的一致性和线程安全,我们经常需要使用到同步机制。其中,`synchronized`关键字是最为常见的一种方式,它能够保证在同一时刻只有一个线程可以访问某个对象的特定代码段。本文将深入探讨`synchronized`关键字的原理、用法以及性能影响,并通过具体示例来展示如何在Java程序中有效地应用这一技术。