【3.0 递归 Recursion 02】
【递归:阶乘】
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】的更多相关文章
- 【2.0 递归 Recursion 01】
[介绍] Java的一个方法可以调用它自己,Java和所有编程语言都可以支持这种情况,我们把它叫做递归Recursion 递归方法是一种调用自身的方法 那么使用递归方法是是怎么样的呢,让我们看看下面这 ...
- Atitit 循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate).
Atitit 循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate). 1.1. 循环算是最基础的概念, 凡是重复执行一段代码, 都可以称之为循环. ...
- 循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate)的区别
表示“重复”这个含义的词有很多, 比如循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate). 循环算是最基础的概念, 凡是重复执行一段代码, 都可以称 ...
- 003_循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate)的区别
表示“重复”这个含义的词有很多, 比如循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate). 循环算是最基础的概念, 凡是重复执行一段代码, 都可以称 ...
- 数据结构与算法--递归(recursion)
递归的概念 简单的说: 递归就是方法自己调用自己,每次调用时传入不同的变量.递归有助于编程者解决复杂的问题,同时可以让代码变得简洁. 递归调用机制 我列举两个小案例,来帮助大家理解递归 1.打印问题 ...
- webug4.0 打靶笔记-02【完结】
webug4.0打靶笔记-02 3. 延时注入(时间盲注) 3.1 访问靶场 3.2 寻找注入点 貌似一样的注入点: ?id=1' --+ 3.3 判断输出位置 同前两关一样的位置,时间盲注应该不是这 ...
- 算法与数据结构基础 - 递归(Recursion)
递归基础 递归(Recursion)是常见常用的算法,是DFS.分治法.回溯.二叉树遍历等方法的基础,典型的应用递归的问题有求阶乘.汉诺塔.斐波那契数列等,可视化过程. 应用递归算法一般分三步,一是定 ...
- 《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. ...
- 【数据结构与算法Python版学习笔记】递归(Recursion)——优化问题与策略
分治策略:解决问题的典型策略,分而治之 将问题分为若干更小规模的部分 通过解决每一个小规模部分问题,并将结果汇总得到原问题的解 递归算法与分治策略 递归三定律 体现了分支策略 应用相当广泛 排序 查找 ...
随机推荐
- vue农历日历
<template> <div class="calendar-main"> <div class="choose_year"&g ...
- c++ winapi 在当前程序(local)调用目标程序(target)的函数
GameCheat stackoverflow 如果你的目标程序是x86/x64, 那么当前程序也需要编译为x84/x64 #include <iostream> #include < ...
- fetch & form-data & upload & image file
fetch & form-data & upload & image file no need multipart/form-data https://blog.xinshan ...
- Markdown简单语法的使用
Markdown简单语法的使用 目录 Markdown简单语法的使用 前言 标题的设置 字体的设置 1.字体加粗 2.斜体 3.字体加粗斜体 3.删除线 引用 列表的使用 插入图片 分割线 代码的书写 ...
- Typescript快速入门
目录 什么是Typescript 为什么学习Typescript 快速搭建开发环境 1.安装node.js 2.使用node自带的npm安装Typescript编译器 3.配置vscode编辑环境 4 ...
- .net实现filestream类复制文件
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.I ...
- 1094 The Largest Generation ——PAT甲级真题
1094 The Largest Generation A family hierarchy is usually presented by a pedigree tree where all the ...
- 微信小程序(四)-样式 WXSS
样式 WXSS https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxss.html 1.尺寸单位 rpx(respons ...
- 永远不要眼高手低,Vue完整实现一套简单的增删改查CURD操作
1: 永远不要眼高手低,看起来很简单,但是你从来没有去动手试一下,就不知道其中真正需要注意的许多细节, 2:完整code如下: 1 <!DOCTYPE html> 2 <html l ...
- ElasticSearch 数据建模
公号:码农充电站pro 主页:https://codeshellme.github.io 通常在使用 ES 构建数据模型时,需要考虑以下几点: 字段类型 是否需要搜索与分词 是否需要聚合与排序 是否需 ...