Java 算法篇-深入理解递归(递归实现:青蛙爬楼梯)

news2024/11/29 10:48:28

🔥博客主页: 小扳_-CSDN博客
❤感谢大家点赞👍收藏⭐评论✍
 

 

文章目录

        1.0 递归的说明

        2.0 用递归来实现相关问题

        2.1 递归 - 阶乘

        2.2 递归 - 反向打印字符串

        2.3 递归 - 二分查找

        2.4 递归 - 冒泡排序

        2.5 递归 - 冒泡排序2.0

        2.6 递归 - 插入排序

        2.7 递归 - 斐波那契

        2.8 递归 - 兔子问题

        2.9 递归 - 青蛙爬楼梯


        1.0 递归的说明

        递归就是在一个函数中调用自身。这样做可以让我们解决一些问题,比如计算斐波那契数列、阶乘等。

        递归函数一般包括两部分:基本情况和递归情况。基本情况是指当问题变得很小,可以直接得到答案时,递归就可以停止了。递归情况是指在解决问题的过程中,需要不断地调用自身来解决更小规模的问题。

        对于递归这个算法,简单的来说,方法自身调用自身的时候,需要有终止的条件,在运行过程中不断的趋向终止条件。还有递归总的来说有两个动作:第一个动作是递出,方法不断的在栈区中创建出来,直到达到了条件就会停止。第二个动作,达到条件停止了,就会回归,指方法在栈区中依次执行完后就销毁。

        2.0 用递归来实现相关问题

        以下的问题都较为简单,采取直接用代码来演示。

        2.1 递归 - 阶乘

代码如下:

    //阶乘
    public static void main(String[] args) {
        System.out.println(fun(5));
    }
    
    public static int fun(int n) {
        if (n == 1) {
            return 1;
        }
        return n * fun(n-1);
    }
}

运行结果为:

        2.2 递归 - 反向打印字符串

代码如下:

    //反向打印字符串
    public static void main(String[] args) {
        String str = "lisi";
        fun2(str,0);
    }

    public static void fun2 (String s, int n) {

        if (n == s.length()) {
            return;
        }
        fun2(s,n + 1);
        System.out.println(s.charAt(n));
    }

运行结果:

        2.3 递归 - 二分查找

代码如下:

    //二分查找
    public static void main(String[] args) {
        int[] arr = {1,3,5,7,9,10,13};
        System.out.println(fun3(arr, 0, arr.length - 1, 4));
    }

    public static int fun3 (int[] arr, int left, int right, int target) {
        int mid = (left + right) >>> 1;
        if (left > right) {
            return -1;
        }
        if(arr[mid] < target) {
            return fun3(arr, mid + 1,right,target);
        } else if (target < arr[mid]) {
            return fun3(arr,left,right - 1,target);
        }else {
            return mid;
        }
    }

  运行结果如下:

        没有找到就返回 - 1

        2.4 递归 - 冒泡排序

代码如下:

    //冒泡排序
    public static void main(String[] args) {
        int[] arr = {1,5,2,4,9,1,3};
        fun4(arr, arr.length - 1);
        System.out.println(Arrays.toString(arr));
    }
    public static void fun4 (int[] arr, int n) {
        if (n == 0) {
            return;
        }
        for (int i = 0; i < n; i++) {
            if (arr[i] > arr[i + 1]) {
                int temp = arr[i];
                arr[i] = arr[i+1];
                arr[i+1] = temp;
            }
        }
        fun4(arr,n-1);
    }

运行结果如下:

        2.5 递归 - 冒泡排序2.0

        对冒泡排序进行升级,假如 int[] arr = {2,1,1,3,4,5,9},这种只需要遍历一遍即可,但是对与已经用递归实现的冒泡不止遍历一次。因此,需要得到升级版冒泡排序。

        思路为:对于后续的元素已经是排好序了,就不用再遍历了。每一次交换完元素之后记下来 i 索引,i 之后的元素已经是排好序的,i 之前的元素还需要继续遍历,看是否还需要交换。

代码如下:

    //冒泡排序升级版
    public static void main(String[] args) {
        int[] arr = {1,3,2,4,9,10,13};
        fun4(arr, arr.length - 1);
        System.out.println(Arrays.toString(arr));
    }
    public static void fun4 (int[] arr, int n) {
        if (n == 0) {
            return;
        }
        int j = 0;
        for (int i = 0; i < n; i++) {
            if (arr[i] > arr[i + 1]) {
                int temp = arr[i];
                arr[i] = arr[i+1];
                arr[i+1] = temp;
                j = i;
            }
        }
        fun4(arr,j);
    }

        如果还不是很清晰的话,可以一步步来调试一下,来对比两种冒泡的执行过程。

        2.6 递归 - 插入排序

        思路:假设第一个元素已经排序好了的,在已经排好的元素的后一个元素记录为 low,这个 low 索引对应的元素需要用临时变量来接受,只要找到比这个索引对应的元素小的值,就可以插入到比它小的值的后一个索引位置了,当然,每一次对比之后,都需要往后移一个位置,以便直接插入。当 low 一直每一个加 1 ,当 low 等于数组的长度时,就该停止了继续递归下去了。

代码如下:

public class Recursion {
    // 插入排序
    public static void main(String[] args) {
        int[] arr = {1,3,2,4,9,10,13};
        fun5(arr,1);
        System.out.println(Arrays.toString(arr));
    }

    public static void fun5 (int[] arr,int low) {
        if (low == arr.length) {
            return;
        }
        int temp = arr[low];
        int i = low - 1;
        while (arr[i] > temp) {
            arr[i + 1] = arr[i];
            i--;
        }
        arr[i + 1] = temp;
        fun5(arr,low + 1);
    }

运行结果如下:

        2.7 递归 - 斐波那契

代码如下:

    //斐波那契
    public static void main(String[] args) {
        System.out.print(fun6(1) +" ");
        System.out.print(fun6(2) +" ");
        System.out.print(fun6(3) +" ");
        System.out.print(fun6(4) +" ");
        System.out.print(fun6(5) +" ");
        System.out.print(fun6(6) +" ");
    }

    public static int fun6 (int n) {
        if (n == 0) {
            return 0;
        }
        if (n == 1 || n == 2) {
            return 1;
        }

        return fun6(n-1) + fun6(n - 2);
    }

运行结果如下:

        2.8 递归 - 兔子问题

        一个斐波那契的变体问题。

        思路:观察第六个月的兔子个数,是否等于第四个月的兔子的总数加上第五个月的兔子总数;类推,第五个月的兔子个数,是否等于第四个月的兔子的总数加上第三个月的兔子总数;以此类推,是符合斐波那契逻辑的。

代码如下:

    //兔子问题
    public static void main(String[] args) {
        System.out.print(fun7(1) + " ");
        System.out.print(fun7(2) + " ");
        System.out.print(fun7(3) + " ");
        System.out.print(fun7(4) + " ");
        System.out.print(fun7(5) + " ");
    }
    
    public static int fun7 (int n) {
        if (n == 1) {
            return 1;
        }
        if (n == 0) {
            return 0;
        }
        return fun7(n -1) + fun7(n - 2);
    }

运行结果如下:

        2.9 递归 - 青蛙爬楼梯

        一个斐波那契的变体问题。

题目如下:

列举一下:

        实现思路: 一个阶梯一种跳法,两个阶梯两种跳法。重点,如果有四个阶梯,从后往前分析,分两种情况;第一种,从第二个台阶直接一下子跳两阶上来。第二种,从第三个台阶跳一阶上来。那么从考虑第一种情况,前面两阶是不是就是只有两种方法。考虑第二种情况,前面的三个台阶是不是就是前面已经算出来的方式跳法个数了。因此,这就是一个斐波那契的变体问题。

代码如下:

    //青蛙问题
    public static void main(String[] args) {
        System.out.print(fun8(1) + " ");
        System.out.print(fun8(2) + " ");
        System.out.print(fun8(3) + " ");
        System.out.print(fun8(4) + " ");
        System.out.print(fun8(5) + " ");
        System.out.print(fun8(6) + " ");
    }

    public static int fun8 (int n) {
        if (n == 1) {
            return 1;
        }
        if (n == 2) {
            return 2;
        }
        return fun8(n-1) +fun8(n-2);
    }

运行结果如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1192090.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vite依赖预构建

本文使用的包管理工具是 npm 开发工具是 vscode 本文作为对 vite的了解性内容即可&#xff0c;实际开发中并不会做太多的工作 依赖预构建干了啥 首先vite会找到对应的依赖&#xff0c; 然后调用 esbuild(对js语法进行处理的一个库)&#xff0c; 将其他规范的代码转换成 esmodu…

虚幻C++基础 day3

常见的游戏机制 Actor机关门 创建一个Actor类&#xff0c;添加两个静态网格与一个触发器 UBoxComponentUStaticMeshComponent 头文件&#xff1a; #include “Components/BoxComponent.h”#include “Components/StaticMeshComponent.h” TriggerDoor.h // Fill out your …

Apinto 网关进阶教程,使用 API Mock 生成模拟数据

什么是 API Mock &#xff1f; API Mock 是一种技术&#xff0c;它允许程序员在不依赖后端数据的情况下&#xff0c;模拟 web服务器端 API 的响应。通常使用 API Mock 来测试前端应用程序&#xff0c;而无需等待后端程序构建完成。API Mock 可以模拟任何 HTTP 请求方法&#x…

ai 问答时刻

妙啊 这很快 相当棒

Queue 中 poll()和 remove()的区别(详解)

系列文章目录 1.SpringBoot整合RabbitMQ并实现消息发送与接收 2. 解析JSON格式参数 & 修改对象的key 3. VUE整合Echarts实现简单的数据可视化 4. List&#xff1c;HashMap&#xff1c;String,String&#xff1e;&#xff1e;实现自定义字符串排序&#xff08;key排序、Val…

k8s-docker二进制(1.28)的搭建

二进制文件-docker方式 1、准备的服务器 角色ip组件k8s-master1192.168.11.111kube-apiserver,kube-controller-manager,kube-scheduler,etcdk8s-master2192.168.11.112kube-apiserver,kube-controller-manager,kube-scheduler,etcdk8s-node1192.168.11.113kubelet,kube-prox…

【Data Grip】数据库和表的创建

目录 1.数据库的创建 2.表的创建 Data Grip 是一款数据管理工具 1.数据库的创建 点击ok 创建完成 2.表的创建 比如创建一个student表 字段名有 id name age gender grade 填写表名之后&#xff0c;右键columns添加字段 搞定id字段&#xff0c;继续右键columns 创…

vnpy_ctp源码下载后转变为python可用的处理过程

目录 写在前面 下载源码并解压 创建python项目 环境 过程 编译vnpy_ctp源码 验证可用性 写在前面 window系统中必须安装有Visual Studio ,后面源码安装时需要进行C编译 下载源码并解压 GitHub - vnpy/vnpy_ctp: VeighNa框架的CTP交易接口 下载zip压缩包 解压 要在…

基于YOLOV8+移动窗口切片(完整版)+OnnxRuntime+KMeans+Zbar+传统图像处理算法的大图片小目标光伏产线条码检测研究

文章目录 前言1 项目背景2 训练YOLOV8的一维码检测模型3 读取测试图片3.1 调整首窗口位置4 创建滑动窗口,窗口大小为(640,640),移动距离为160,对不足(640,640)的窗口进行填充5 创建Onnxruntime推理引擎并测试5.1推理测试5.2获得ONNX模型输入层(输出层)和数据维度5.3 …

C++20 Text formatting

C20 Text formatting 格式化字符串&#xff0c; 和 python 类似。 std::formatter - cppreference.com string — Common string operations — Python 3.12.0 documentation 新格式库位于 <format> 头文件中。格式库基于 Python3 中的 str.format() 方法建模。格式…

划分VOC数据集,以及转换为划分后的COCO数据集格式

1.VOC数据集 LabelImg是一款广泛应用于图像标注的开源工具&#xff0c;主要用于构建目标检测模型所需的数据集。Visual Object Classes&#xff08;VOC&#xff09;数据集作为一种常见的目标检测数据集&#xff0c;通过labelimg工具在图像中标注边界框和类别标签&#xff0c;为…

MySQL单表过大、主从模式、同步模式优化原理

文章目录 MYSQL单表数据达2000万性能严重下降?前言InnoDB索引数据结构B树 Sharding Sphere分库分表Sharding-JDBCSharding-JDBC的相关概念说明逻辑表广播表绑定表 Sharding-JDBC中的分片策略自动分片算法取模分片算法哈希取模分片算法分片容量范围标准分片算法行表达式分片算法…

第1章 现代通信网概述

文章目录 1.1 通信网的定义1.2 通信网的分类1.3 通信网的结构1.4 通信网的质量要求 1.1 通信网的定义 1.1.1 通信系统 1.1.2 通信网的定义 通信网是由一定数量的节点 (包括终端节点、交换节点) 和连接这些节点的传输链路有机地组织在一起&#xff0c;以实现两个或多个规…

JWFD开源工作流-随机函数发生器最新进展

使用WIN7 32位&#xff0c;JDK1.8平台&#xff0c;跑语法分析&#xff0c;实测结果如上图&#xff0c;比JDK1.6的每个函数计算速度快了不止100倍&#xff0c;升级为JDK1.8是正确的选择&#xff0c;这个模块是典型的变形函数计算单元&#xff0c;可以解决很多需要动态变形物理模…

阿里云竞争加剧,腾讯云双十一服务器优惠力度爆表!

腾讯云对于新客户和老客户都有相互照顾的优惠力度。特别是在今年的双十一活动中&#xff0c;腾讯云推出了一系列的优惠活动。首先&#xff0c;轻量服务器和云服务器产品的首购活动中&#xff0c;三年的云服务器仅需540元&#xff0c;这是一个非常低廉的价格。其次&#xff0c;香…

linux下俺安Anaconda

文章目录 一、linux下安装anaconda1 下载anaconda的安装包2 安装anaconda3设置环境变量4完成安装以及检测是否安装成功 二、linux下配置并运行![在这里插入图片描述](https://img-blog.csdnimg.cn/30a818b7a0b24d81aceef93e2d365b7e.png)1、一般情况下&#xff0c;anaconda中默…

标本传送设备物联网应用案例|蓝蜂物联网一体化方案

标本传送设备物联网应用案例 标本传输系统被大量应用到现代医院场景中&#xff0c;系统各个设备的运行情况直接影响到整个医院系统的正常稳定&#xff0c;所以对于标本传输系统的实时监控和及时运维是维持医院稳定和规避风险的重中之重。 针对标本传输系统应用过程中的数据统…

HTML5学习系列之简单使用1

HTML5学习系列之简单使用1 前言基础显示学习定义网页标题定义网页元信息定义网页元信息定义文档结构div元素di和classtitlerole注释 总结 前言 下班加班期间的简单学习。 基础显示学习 定义网页标题 <html lang"en"> <head> <title>从今天开始努…

WPS的JS宏基础(二)

数据的输入和输出 InputBox(‘请输入内容’) //输入框 alert(‘a’) //简单消息框 MsgBox(‘b’) //进阶消息框 Debug.Print(‘c’) //立即窗口 Console.log(‘d’) //立即窗口 编写规则与注释 1.严格遵循大小写规范 2.每条语句之间用分号分隔 3.复合语句块&#xff08;块中…

Ionic组件 ion-list ion-list-header

1 ion-list 列表由多行项目组成&#xff0c;这些项目可以包含 text, buttons, toggles, icons, thumbnails等。列表通常包含具有类似数据内容的项目&#xff0c;如 images and text。 列表支持多种交互&#xff0c;包括滑动项目以显示选项、拖动以重新排列列表中的项目以及删除…