【递归:阶乘】

1.寻找基本情况

对于阶乘而言,最基本的情况就是0!和1!,二者的结果都是1

我们不妨现在方法中写下这个情况,帮助我们跳出递归

if(i<=1){
return 1 ;
}

接下来,如果不是1或0,则进行阶乘运算

public static int Factorial (int i){
if(i<=1){
return 1 ;
}else {
return (i*Factorial(i - 1)) ;
}
}

思路很简单,我们从n开始放入,计算n!就需要(n-1)!,计算(n-1)!需要(n-2)!,以此递推到1!

下面是对于这次操作的栈的示意图(以5为例)

建立堆栈(递归的过程

开始执行的时候,是从Factoria(1)逐级返回,最终得到5*4!即返回的过程

【递归:三角数】

三角数就像是加法的“阶乘”,必然1+2+3+4...

首先还是先寻找最初始的情况,显然那就是1了

和阶乘一样,我们也利用“堆栈——返回”的操作来进行三角数的计算

我们观察发现:出现一个模式即 T(n)= T(n –1)+ n 这种模式将有助于对三角数程序的递归进行程序编写。

public static int TrianNum(int i){
if(i<=1){
return 1 ;
}else {
return (i+TrianNum(i - 1)) ;
}
}

【斐波纳契数列 Fibonacci Numbers】

斐波那契数列:前两个数之后的每一个数都是前两个数的和

我们可以通过下面这个方程来描述斐波纳契数列

迭代的角度来看斐波那契数列:

为了计算任何斐波那契数“n”,我们需要知道斐波那契数“n -1”和“n -2”,对于迭代版本,我们从第一个数字(n = 0)开始

随后我们计算1,2两个数字,之后是2,3,然后是3,4...以此不断推进,那么可以按照这个思想得到下面这个算法

public static int FibIter(int n){
int prevl =0 , prev2 = 1 ;
int savePrev1 = 0 ;
for(int i = 0 ; i <n ; i ++){
savePrev1 = prev1 ;
prev1 = prev2 ;
prev2 = savePrev1 + prev2 ;
}
return prev1 ;
}

递归的角度来看斐波那契数列:

在之前的方程中,实质上已经包含的基本情况和递归步骤

我们可以得到在递归角度的如下代码:

public static int Fib(int n){
if(n == 0 ) {
return 0 ;
}
else if(n == 1 ) {
return 1 ;
//注意,这里是else if ,当第一个基本情况不满足时,才去判定第二个。当二者都不符合,再进入递归步骤
}else{
return Fib(n-1) + Fib(n-2) ; //就是这一步,实质上实现了F(n) = F(n-1) + F(n-2) 的操作
}

迭代递归两种方法得到的答案是一样的,但是运行的过程和核心是非常不同的

采用递归的思想进行计算时,先不断堆栈达到基本情况(0或1),然后再由基本情况向目标推进

【递归:函数功能定义 Functional Definitions】

我们经常会遇到用递归函数定义的问题——就像我们在斐波那契数列中看到的那样,问题的定义通常用数学的方法(方程)写成

就像这种形式的方程,我们便可以使用递归

在这种情况下,递归常常会比迭代更加直观

public static int FuncA(int n) {
if(n == 1 ){
return 4 ;
}else{
return (5* Func(n-1)+10);
}
}

【递归与数组 Recursion with Arrays】

递归还可以用于查找存储在数组中的最大值和最小值,让我们尝试一个寻找数组最大值的例子:

首先是找到基本情况,我们将假定将从当前元素开始遍历整个数组。基本情况是,当我们查看数组中的最后一个元素的时候————这时候我们已经知道了我们遍历了数组中的所有元素,所以我们从此跳出递归

那么递归步骤呢,这个其实很简单:我们将每个元素与当前存储的最大元素进行比较,如果当前正在查看的元素大于当前最大存储元素,则将该值更新为新的最大值

附:Math.max : Math.max(int a, int b),会返回a、b中的较大者,需要import java.lang.* ; 后使用


public static int maxArray(int [] array , int start){
if(start == array.lengrh - 1){
return array[start] ; //一个基本情况:仅有一个数字的数组,代表需要结束了
}else{
return (Math.max(array[start],maxArray(array,start + 1)));
}
}

可能光看代码比较抽象,来看看这张示意图:

【小结:递归的优缺点】

缺点:

•递归反复调用该方法,该方法在内存和处理时间方面会产生成本

•每次递归调用都会创建该方法的另一个副本(及其所有变量)

•这种方法的复制会消耗大量的内存空间

优点:

•如果我们对原始问题做一些细微的改变,就会更容易找到递归的解决方案

•有时,递归解决方案的运行速度会比迭代解决方案慢,不过,在大多数情况下,它只是稍微慢一些

•在许多情况下,递归解决方案比迭代解决方案更容易理解和编写代码

【3.0 递归 Recursion 02】的更多相关文章

  1. 【2.0 递归 Recursion 01】

    [介绍] Java的一个方法可以调用它自己,Java和所有编程语言都可以支持这种情况,我们把它叫做递归Recursion 递归方法是一种调用自身的方法 那么使用递归方法是是怎么样的呢,让我们看看下面这 ...

  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. webug4.0 打靶笔记-02【完结】

    webug4.0打靶笔记-02 3. 延时注入(时间盲注) 3.1 访问靶场 3.2 寻找注入点 貌似一样的注入点: ?id=1' --+ 3.3 判断输出位置 同前两关一样的位置,时间盲注应该不是这 ...

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

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

  8. 《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. ...

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

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

随机推荐

  1. 「NGK每日快讯」11.18日NGK公链第15期官方快讯

  2. Python数据结构与算法_最长公共前缀(05)

    编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower","flow" ...

  3. Prometheus时序数据库-内存中的存储结构

    Prometheus时序数据库-内存中的存储结构 前言 笔者最近担起了公司监控的重任,而当前监控最流行的数据库即是Prometheus.按照笔者打破砂锅问到底的精神,自然要把这个开源组件源码搞明白才行 ...

  4. (原创)用.NET Core实现微信自动回复工具(上篇)

    全文 没有视频的介绍显得尤为空白仓促.所以,如果你不赶时间,看看视频先 → → http://wexin.fuyue.xyz/Resource/Video/wechatTool.mp4 ← ← 功能列 ...

  5. 微信小程序:列表渲染

    wx:for,(wx:for-item,wx:for-index),wx:key. 列表循环包括数组循环和对象循环 一.数组循环 此时控制台报错如下:属性"wx:key"可以提高性 ...

  6. Win32Api -- 关闭当前应用

    本文介绍Windows系统下使用Win32API获取当前应用并关闭的方法. 思路 使用EnumWindows接口枚举当前窗口; 过滤掉不可用.隐藏.最小化的窗口: 过滤掉子窗口: 通过标题.类名过滤掉 ...

  7. MarkDown简单语法回顾

    写在前面: 本文是我的第一篇博客文章,希望与大家共同交流.分享我们热爱的技术,努力成为一名优秀的软件工程师! 进入正文 使用MarkDown记笔记已经有些时候了,编辑器是使用的sublime text ...

  8. 由endl对printf和cout的思考

    [前言]二者的区别就不介绍了.二者使用方法: printf("%s",a); cout<<a<<endl; endl的作用是什么? 一.endl作用 众所周 ...

  9. java帝国的诞生

    Java : 一个帝国的诞生 C语言帝国的统治 现在是公元1995年, C语言帝国已经统治了我们20多年, 实在是太久了. 1972年, 随着C语言的诞生和Unix的问世, 帝国迅速建立统治, 从北美 ...

  10. 普通的一天,说一个普通的XML

    什么是XML XML全称是Extensible Markup Language,译为"可扩展标记语言",常用来存储和传输信息. XML的结构 我们经常看到的XML文件是这个样子的: ...