【介绍】

Java的一个方法可以调用它自己,Java和所有编程语言都可以支持这种情况,我们把它叫做递归Recursion

递归方法是一种调用自身的方法

那么使用递归方法是是怎么样的呢,让我们看看下面这段代码

(由于复制粘贴代码还要考虑排版,这里就上图了)

结果是程序会一直在调用这个方法,直到内存不足而停止(无限套娃)

【概念】

方法反复调用自身的概念称为递归

方法会不断调用自身,直到达到某些停止条件为止,有点像循环语句

在没有停止条件的情况下,程序将循环运行,直到计算机(Java虚拟机)内存不足(拒绝分配更多的内存)为止

虽然递归可能显得浪费甚至效率低下,但它在计算机科学和数学中是一个非常重要的概念

递归更像是一种思想,我们需要打破原有的“迭代”的思维定势(for,while)

为了帮助可视化“递归”,我们将使用一个称为堆栈 Stack的通用概念

堆栈基本上像自助餐厅中的托盘容器一样工作。它只有两个操作:

Push:你可以把某个东西压到栈上

Pop:你可以从堆栈的顶部弹出一些东西

First In Last Off

通过下面这张图感受一下

有的人说这就像弹匣一样,拉出来装Push然后从第一发开始射击Pop

【堆栈和方法 Stacks and Methods】

当你运行一个程序时,计算机会为你创建一个堆栈

每次调用方法时,该方法都会放在堆栈的顶部

当方法返回或退出时,该方法将从堆栈中弹出

【堆栈和递归 Stacks and Recursion】

每次调用方法时,都将该方法推入堆栈

每次方法返回或退出时,都将方法弹出堆栈

如果一个方法递归地调用自己,您只需将该方法的另一个副本压入堆栈

对于下面的这个简单程序:

public class Recursion1V0{
public static void main (String args[]) {
count(0);
System.out.println();
}
public static void count (int index) {
System.out.print(index);
if (index < 2) count(index+1);
}
}

我们将这个过程可视化之后便是这样

如果我们把代码改成

public class Recursion1V0{
public static void main (String args[]) {
count(0);
System.out.println();
}
public static void count (int index) { if (index < 2) count(index+1);
System.out.print(index); //注意这里!
}
}

此时的输出是2 1 0 为什么呢,我们回忆一下堆栈的Push和Pop,就知道为什么了(FirstIn,LastOff)

我们需要一个方法执行结束(return好了),再执行接下来的操作

count(0)到count(1)到count(2),结束执行,随后执行System.out.print(index),分别打印210

【两种类型的递归】

1.直接递归 Direct recursion

方法直接包含对自身的引用或调用

2.间接递归 Indirect Recursion

一个方法调用另一个方法,该方法最终调用原始方法(比如A方法调用B方法,B方法调用A方法)

递归计算通过使用相同问题的解决方案来解决问题,但是具有更简单的值。我们称此为递归步骤 recursive step

为了使递归终止或停止,还必须有最简单值的特殊情况,我们称之为基本情况base case/anchor case/stopping condition

基本情况是为输入参数的一个或多个已知值指定方法值的情况

递归步骤(或归纳步骤)是根据先前定义的值定义对参数的当前值所采取的操作

为了执行递归,我们必须考虑以下两个方面

1.如何解决最简单的问题

2.给定一个更复杂的问题实例,如何使其更像最简单的实例?即如何使它更接近问题的最简单实例(使其像基本情况一样)?

【三步使用递归 Three Steps to Recursive Success 】

动手试试,我们写一个程序来检测字符串是否是回文(比如NAVAN)

1.减少 Reduction ——使问题变小

可以直接检测首尾的字符,如果它们是相同的,那么我们就删除它们(如果一开始就是回文如NAVAN,那么删除后得到的部分也是回文AVA)

2.基本情况 Base Cases ——处理简单的值,关键是找到最简单的情况的解决方案

比如有下面几个情况

1.最后没有字符了——是回文

2.最后剩下一个字符——是回文

3.最后剩下两个字符且二者不是同一个字符——不是回文

3.执行 Implement ——结合基本情况与步骤

【2.0 递归 Recursion 01】的更多相关文章

  1. 【3.0 递归 Recursion 02】

    [递归:阶乘] 1.寻找基本情况 对于阶乘而言,最基本的情况就是0!和1!,二者的结果都是1 我们不妨现在方法中写下这个情况,帮助我们跳出递归 if(i<=1){ return 1 ; } 接下 ...

  2. Atitit  循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate).

    Atitit  循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate). 1.1. 循环算是最基础的概念, 凡是重复执行一段代码, 都可以称之为循环. ...

  3. 循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate)的区别

    表示“重复”这个含义的词有很多, 比如循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate). 循环算是最基础的概念, 凡是重复执行一段代码, 都可以称 ...

  4. 003_循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate)的区别

    表示“重复”这个含义的词有很多, 比如循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate). 循环算是最基础的概念, 凡是重复执行一段代码, 都可以称 ...

  5. 数据结构与算法--递归(recursion)

    递归的概念 简单的说: 递归就是方法自己调用自己,每次调用时传入不同的变量.递归有助于编程者解决复杂的问题,同时可以让代码变得简洁. 递归调用机制 我列举两个小案例,来帮助大家理解递归 1.打印问题 ...

  6. 算法与数据结构基础 - 递归(Recursion)

    递归基础 递归(Recursion)是常见常用的算法,是DFS.分治法.回溯.二叉树遍历等方法的基础,典型的应用递归的问题有求阶乘.汉诺塔.斐波那契数列等,可视化过程. 应用递归算法一般分三步,一是定 ...

  7. 《javascript高级程序设计》第七章 递归recursion

    7.1 递归7.2 闭包 7.2.1 闭包与变量 7.2.2 关于this 对象 7.2.3 内存泄漏 7.3 模仿块级作用域7.4 私有变量 7.4.1 静态私有变量 7.4.2 模块模式 7.4. ...

  8. HDU 4370 0 or 1 (01规划)【Dijkstra】||【spfa】

    <题目链接> 题目大意: 一个n*n的01矩阵,满足以下条件 1.X12+X13+...X1n=12.X1n+X2n+...Xn-1n=13.for each i (1<i<n ...

  9. 【数据结构与算法Python版学习笔记】递归(Recursion)——优化问题与策略

    分治策略:解决问题的典型策略,分而治之 将问题分为若干更小规模的部分 通过解决每一个小规模部分问题,并将结果汇总得到原问题的解 递归算法与分治策略 递归三定律 体现了分支策略 应用相当广泛 排序 查找 ...

随机推荐

  1. HQYJ嵌入式学习笔记——C语言复习day1

    第一天:Linux命令 vim操作 第二天:数据类型 运算符 顺序语句第三天:分支语句 循环语句第四天:循环语句 数组第五天:数组第六天:指针第七天:函数 数组与指针第八天:数组指针第九天:递归 第十 ...

  2. 为什么ElasticSearch比MySQL更适合全文索引

    熟悉 MySQL 的同学一定都知道,MySQL 对于复杂条件查询的支持并不好.MySQL 最多使用一个条件涉及的索引来过滤,然后剩余的条件只能在遍历行过程中进行内存过滤,对这个过程不了解的同学可以先行 ...

  3. Linux/UNIX编程如何保证文件落盘

    本文转载自Linux/UNIX编程如何保证文件落盘 导语 我们编写程序write数据到文件中时,其实数据不会立马写入磁盘,而是会经过层层缓存.每层缓存都有自己的刷新时机,每层缓存都刷新后才会写入磁盘. ...

  4. 《Effective Java》总结

    导语 <Effective Java>是和<Thinking in java>齐名的java进阶书籍.作者参与了JDK标准库的编写工作,对于此书的学习,让我收获很多.好记性不如 ...

  5. SpringBoot2.2.5整合ElasticSearch7.9.2

    1:前言 为什么是SpringBoot2.2.5,不是其他的SpringBoot版本,原因有两个: 1:SpringBoot2.2.0以上才能支持ElasticSearch7.x版本. 2:Sprin ...

  6. Linux的启动过程及init进程

    Linux下有三个特殊进程: idle进程(pid=0)idle进程其前身是系统创建的第一个进程,0号进程,也唯一一个没有通过fork()或者kernel_thread产生的进程,由系统自动创建,运行 ...

  7. 保证软件开发过程遵循ISO 26262功能安全标准的十个主要进阶步骤

    保证软件开发过程遵循ISO 26262功能安全标准的十个主要进阶步骤 为保障汽车软件质量,使软件开发符合ISO 26262功能安全标准,需要我们对开发流程做出改进,并与2018年的更新同步. 本视频课 ...

  8. PAT-1153(Decode Registration Card of PAT)+unordered_map的使用+vector的使用+sort条件排序的使用

    Decode Registration Card of PAT PAT-1153 这里需要注意题目的规模,并不需要一开始就存储好所有的满足题意的信息 这里必须使用unordered_map否则会超时 ...

  9. 【资源下载】Linux下的Hi3861一站式鸿蒙开发烧录(附工具)

    下载附件 2021春节前夕,华为发布了 HUAWEI DevEco Device Tool 2.0 Beta1,整体提供了异常强大的功能.得知消息后,我在第一时间带着无比兴奋的心情下载尝鲜,但结果却是 ...

  10. 如何在 C# 中使用 const,readonly,static

    平时在开发时经常会用到 const,readonly,static 关键字,可以肯定这些关键词是完全不同的概念,但有时候他们在用法上很相似以至于在场景中不知道选择哪一个,这篇文章我们就来讨论 C# 中 ...