【递归:阶乘】

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. Flutter 使用高德地图定位

    amap_location 包 获取debug SHA1 // 使用debug.keystore获取debug SHA1 C:\Users\ajanuw\.android>keytool -li ...

  2. Flutter 避免阻塞ui线程

    import 'dart:async'; import 'dart:isolate'; import 'package:flutter/material.dart'; import 'package: ...

  3. Element-UI使用相关问题

    1.如何修改el-dialog的样式? 要修改dialog的样式不能直接在<style scoped>中修改,这样修改后不会生效.做法是把scoped去掉,然后在dialog标签上自定义一 ...

  4. 调度场算法&&中缀表达式=>后缀表达式

    #include<stdio.h> #include<string.h> int main(void){ char ch,stro[1001],stack[1001]; int ...

  5. 保姆级别学生党安装Clion IDE(面向华师同学)

    保姆级别学生党安装Clion IDE(面向华师同学) 界面UI 废话不多说,直接上图 具备功能 UI美观 (下面会介绍) 基础的代码编写能力 大容量的IDE插件 (下面会介绍) 代码补全,以及搭配Ki ...

  6. 215. 数组中的第K个最大元素 + 快速排序 + 大根堆

    215. 数组中的第K个最大元素 LeetCode-215 另一道类似的第k大元素问题:https://www.cnblogs.com/GarrettWale/p/14386862.html 题目详情 ...

  7. 【白话科普】CDN & 游戏加速器,两者是一个原理吗?

    说起加速,大家可能就会联想到"游戏加速"之类的场景,而说到现在流行的云服务加速,则离不开 CDN 这个词.那么 CDN 和游戏加速器是同一种东西么?从效果上看两者都是为了" ...

  8. Linux下找出吃内存的方法总结

    Linux下查询进程占用的内存方法总结,假设现在有一个「php-cgi」的进程 ,进程id为「25282」. 现在想要查询该进程占用的内存大小.linux命令行下有很多的工具进行查看,现总结常见的几种 ...

  9. Ubuntu pip版本的安装,卸载,查看,更新

    pip版本的安装: sudo apt-get install python3-pip pip版本的查看: pip3 --version pip3 -V pip更新: sudo pip3 install ...

  10. [POJ2828] Buy Tickets(待续)

    [POJ2828] Buy Tickets(待续) 题目大意:多组测试,每组给出\(n\)条信息\((a,b)\),表示\(b\)前面有\(a\)个人,顺序靠后的信息优先级高 Solution.1 由 ...