算法【Java】—— 递归

news2024/11/25 15:06:38

递归思路

首先我们要分析主问题,如果主问题可以拆分成一个又一个小问题的时候,并且这些小问题的解决方案也是一样的话,我们可以使用递归来解决。

递归函数头的设计是根据子问题的解决需要而设计的

函数体部分则是由如何解决子问题组成

最后就是递归的出口,其实就是分到不能再分的情况。

这里我们不要进行递归展开图的绘制,要相信我们的函数可以完成任务,就像相信你的编译器能进行代码的编译。

下面我们来实战演示一下:

实战演练

汉诺塔

https://leetcode.cn/problems/hanota-lcci/description/

在这里插入图片描述

太经典的题目了,这里就直接分析了,不解析题意了。

我们抽象一下,假设我们有 N 个盘子,我们需要先将 N - 1 个盘子借助 C 柱子 移动到 B 柱上,然后将 A 柱 上 的最后一个盘子直接移动到 C 柱上,最后我们将 B 柱 上的 N - 1 个盘子借助 A 柱 移动到 C 柱上

那么我们的递归函数头的设计应该是盘子数量 , 三个柱子(初始位置,助力位置,目标位置)

递归的出口就是不能继续划分的情况也就是只有一个盘子的情况。

class Solution {
    public void move(List<Integer> A, List<Integer> B, List<Integer> C, int n) {
        if(n == 1) {
            C.add(A.remove(A.size() - 1));
            return;
        }
        move(A, C, B, n - 1);
        C.add(A.remove(A.size() - 1));
        move(B, A, C, n - 1);
    }
    public void hanota(List<Integer> A, List<Integer> B, List<Integer> C) {
        int n = A.size();
        move(A, B, C, n);
    }
}

合并两个链表

https://leetcode.cn/problems/merge-two-sorted-lists/description/
在这里插入图片描述

这道题我们可以采用递归的思路来写,首先找到子问题:
在这里插入图片描述
当我们遇到两条链表的时候,我们会选取其中一个 value 值较小的作为新链表的下一个连接结点,你会发现,每次遇到两条非空链表,都是重复上面的操作,所以函数头的参数也就是两条链表。

接着就是函数体的书写,首先需要比较,然后我们思考这个函数是做什么的?很显然,这个函数需要返回一个结点,这个结点需要连接到上一个递归函数的结点后面,所以这个函数应该是返回两个链表的合适的结点。

递归的出口,当其中一条链表为空的时候,返回另一条链表即可。

class Solution {
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        if(list1 == null) return list2;
        if(list2 == null) return list1;
        ListNode min = list1.val < list2.val ? list1 : list2;
        if(min == list1) 
            min.next = mergeTwoLists(list1.next, list2);
        else 
            min.next = mergeTwoLists(list1, list2.next);
        return min;
    }
}

反转链表

https://leetcode.cn/problems/reverse-linked-list/description/

在这里插入图片描述

递归的函数的作用:反转链表,返回新的头节点

函数头的设计:需要一个链表参数

函数体设计:当我们使用递归函数会得到类似下图的链表:
在这里插入图片描述

当我们得到新的头节点时,我们需要将head.next 这个结点的 next 区域的指向修改为 head, 然后我们还需要将 head 的 next 域修改为 null,为什么需要这个操作,因为最后一个结点的时候,例如上面的 1 号结点,它的next 域指向为空,为了操作的统一,所以这里统一处理为 head.next = null

递归的出口,当 head 为空或者 head 后面没有结点,这时候无需反转链表,直接返回即可。

class Solution {
    public ListNode reverseList(ListNode head) {
        if(head == null || head.next == null) {
            return head;
        } 
        ListNode newHead = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return newHead;
    }
}

两两交换链表中的节点

https://leetcode.cn/problems/swap-nodes-in-pairs/description/

在这里插入图片描述

函数作用:返回一个交换过的链表的头节点,函数头需要一个参数也就是链表的头节点

函数体的设计:
在这里插入图片描述
head.next = 递归函数返回的头节点
r2.next = head

递归的出口:当头节点为空,或者头节点后面没有节点的时候,直接返回头节点即可

class Solution {
    public ListNode swapPairs(ListNode head) {
        if(head == null || head.next == null) {
            return head;
        }
        ListNode r2 = head.next;
        head.next = swapPairs(r2.next);
        r2.next = head;
        return r2;
    }
}

快速幂

https://leetcode.cn/problems/powx-n/

在这里插入图片描述

快速幂的方法:假设求 100 的 10 次方:
在这里插入图片描述
先求出一半的次方的幂,然后进行自我相乘,如果次方为奇数,则需要再乘 一个 x

那么这个递归函数的作用就是来求出快速幂的,传参有两个, x 和 n

在进行递归之前,我们先处理一下如果次方是负数的情况,需要进行转换,由于负数最小为 2 ^ -31 ,所以转化成(int 类型)的正数的时候,会发生溢出,这里就整型提升一下。

递归的出口:n == 0 ,返回1 ,n == 1 返回 自身。

class Solution {
    public double myPow(double x, int n) {
        return n < 0 ? 1 / pow(x, -(long)n) : pow(x, n);
    }

    double pow(double x, long n) {
        if(n == 0) return 1;
        if(n == 1) return x;
        double y = pow(x, n / 2);
        return n % 2 == 0 ? y * y : y * y * x;
    }
}

递归与循环,搜索,回溯,剪枝的关系

递归和循环都是在重复做一件事情,所以递归和循环是可以相互转换的,当然有时候题目使用递归会好写代码,而有些题目使用循环会好写,这是因为我们递归如果是单分支的树,使用循环会更好,但是如果递归是二叉甚至 N 叉树的时候,使用循环就需要借助栈,,这时候循环就很难写了。

我们来看一下搜索,搜索分为广度优先遍历和深度优先遍历,学过图的老铁们应该很清楚,而我们的递归则是和深度优先遍历一样(简称深搜),所以搜索本质上也是递归,没有很神秘。

回溯,这个大家应该有听过回溯算法,实际还是和递归 / 搜索一样,回溯在递归里的表现就是递归到了底,然后向上回去,回去就是回溯。

剪枝可以说是递归 / 搜索 / 回溯的一个优化,就是你发现有些递归是不需要做的,就不进去递归,简单来看就是一个树有很多的岔路,当你知道有一条岔路绝对不可能是答案的时候,这时候使用剪枝就可以去掉这些没有的树枝,在代码理解来看就是不去这个递归。

在后续的算法文章中我会进行对上面的知识进行题目的代码演示与讲解,这里先抛出这些概念。

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

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

相关文章

0基础学习CSS(十六)尺寸和Display(显示) 与 Visibility(可见性)

CSS 尺寸 (Dimension) 所有CSS 尺寸 (Dimension)属性 属性描述height设置元素的高度。line-height设置行高。max-height设置元素的最大高度。max-width设置元素的最大宽度。min-height设置元素的最小高度。min-width设置元素的最小宽度。width设置元素的宽度。 CSS Display(显…

【算法】---快速排序

参考 左神和神书算法导论. 学习前置 了解并实现过快速排序。 笔者曾经在数据结构篇写过快速排序&#xff0c;现在面向算法篇快排。 快速排序 输入数据所有排列是等概率的&#xff0c; 这种情况对于实际工程上不会总是成立。朴素快速排序对于特定的输入很糟糕&#xff0c; …

PASCAL VOC 2012数据集 20类物体,这些物体包括人、动物(如猫、狗、鸟等)、交通工具(如车、船、飞机等)以及家具(如椅子、桌子、沙发等)。

VOC2012数据集是PASCAL VOC挑战赛官方使用的数据集之一&#xff0c;主要包含20类物体&#xff0c;这些物体包括人、动物&#xff08;如猫、狗、鸟等&#xff09;、交通工具&#xff08;如车、船、飞机等&#xff09;以及家具&#xff08;如椅子、桌子、沙发等&#xff09;。每个…

ultralytics-yolo-webui :Detect 目标检测 工具-先行版本 >> DataBall

通过webui 方式对ultralytics 的 detect 检测任务 进行&#xff1a; 1&#xff09;数据预处理&#xff0c;2&#xff09;模型训练&#xff0c;3&#xff09;模型推理。 本项目提供了 示例数据集&#xff0c;用 labelImage标注&#xff0c;标注文件为 xml 文件。 项目地址&…

数据结构(栈和队列的实现)

1. 栈&#xff08;Stack&#xff09; 1.1 栈的概念与结构 栈是一种特殊的线性表&#xff0c;其只允许固定的一段插入和删除操作&#xff1b;进行数据插入和删除的一段叫做栈顶&#xff0c;另一端叫栈底&#xff1b;栈中的元素符合后进先出LIFO&#xff08;Last In First Out&…

PCL 点云半径滤波

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.1.1 半径滤波实现 2.1.2 可视化函数 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接&#xff1a; PCL点云算法与项目实战案例汇总&#xff08;长期更新&#xf…

MFC有三个选项:MFC ActiveX控件、MFC应用程序、MFC DLL,如何选择?

深耕AI&#xff1a;互联网行业 算法研发工程师 ​ 目录 MFC ActiveX 控件 控件的类型 标准控件 自定义控件 ActiveX控件 MFC ActiveX控件 标准/自定义控件 MFC ActiveX控件分类 3种MFC如何选择&#xff1f; MFC ActiveX控件 MFC 应用程序 MFC DLL 总结 举例说明…

【JAVA开源】基于Vue和SpringBoot的周边产品销售网站

本文项目编号 T 061 &#xff0c;文末自助获取源码 \color{red}{T061&#xff0c;文末自助获取源码} T061&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 查…

申请免费或试用VPS服务

申请免费或试用VPS服务 有时候我们特别希望能够找到一台像 Oracle Cloud 一样的永久免费 VPS&#xff08;需要满足一定的条件&#xff09;&#xff0c;可相对于其它厂商申请相对比较难&#xff0c;可能需要多次申请才能得到。其实&#xff0c;除了 Oracle Cloud 之外&#xff0…

阿里云对象存储OSS 速学

目录 1.创建一个Bucket 2.创建密钥AccessKey 3.在文档中心打开阿里云对象存储OSS 4.参考上传文件示例 以官网的文档为主&#xff0c;我的文章教学为辅 官网有详细的视频介绍&#xff1a; OSS快速入门_对象存储(OSS)-阿里云帮助中心 (aliyun.com)https://help.aliyun.com/…

Linux: network: 典型网络延迟图,CPU导致;

接上回说&#xff0c;https://mzhan017.blog.csdn.net/article/details/142689870&#xff1b; 其中在debug的过程中&#xff0c;看到下面这个IO图&#xff0c;这个图比较经典&#xff0c;是一个典型的网络延迟图&#xff0c;可用作为分析问题的一个参考。 如下图&#xff1a;黑…

C++ | Leetcode C++题解之第454题四数相加II

题目&#xff1a; 题解&#xff1a; class Solution { public:int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) {unordered_map<int, int> countAB;for (int u: A) {for (int v: B) {count…

ZYNQ: GPIO 之 EMIO 按键控制 LED 实验

GPIO 之 EMIO 按键控制 LED 实验目的 使用启明星 ZYNQ 底板上的两个用户按键分别控制 PS 端两个 LED 的亮灭 其中一个按键 PL_KEY0 连接到了 PL 端&#xff0c;需要通过 EMIO 进行扩展&#xff0c;另外一个按键是底板上 PS 端的用户按键PS_KEY0&#xff0c;这两个按键分别控制…

堆的向上和向下调整

堆的物理结构和逻辑结构是什么&#xff1f; 堆如何插入数据和删除数据&#xff1f;为什么&#xff1f; 向上调整和向下调整的要求是啥&#xff1f; 文中不理解的可以先看堆的代码和基础知识-CSDN博客 也欢迎评论区一起讨论 1.堆的物理结构和逻辑结构 我们的堆是用数组实…

计算机毕业设计 视频点播系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

【AI知识点】维度灾难(curse of dimensionality)

维度灾难&#xff08;curse of dimensionality&#xff09; 是指在处理高维数据时&#xff0c;随着维度的增加&#xff0c;数据的性质和空间结构变得越来越复杂&#xff0c;导致许多常见的算法和技术在高维空间中效率低下或效果变差的问题。 这个概念最早是由Richard Bellman在…

RabbitMQ篇(基本介绍)

目录 一、MQ 1. 什么是MQ 2. 为什么要用MQ【业务场景】 2.1. 异步 2.2. 应用解耦 2.3. 流量削峰 3. MQ的分类 &#xff08;1&#xff09;ActiveMQ &#xff08;2&#xff09;Kafka &#xff08;3&#xff09;RocketMQ &#xff08;4&#xff09;RabbitMQ 4. MQ 的选…

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-02

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-02 1. APM: Large Language Model Agent-based Asset Pricing Models Authors: Junyan Cheng, Peter Chin https://arxiv.org/abs/2409.17266 APM: 基于大型语言模型的代理资产定价模型&#xff08;LLM Agent-b…

2、项目配置设计(上)

文章目录 前言一、配置文件功能需求二、web工程设计思路三、Config实现思路 前言 配置文件作用&#xff1a;把需要经常修改的参数&#xff0c;从代码中分离出来,单独管理&#xff0c;方便后期维护。 开发一个web应用&#xff0c;肯定需要一些基础性的配置信息&#xff0c;这些信…

骨架屏 (懒加载优化)

骨架屏 &#xff08;懒加载优化&#xff09; 即便通过 Webpack 的按需加载、CDN 静态资源缓存 和 代码分割 等技术来减少首屏的代码体积&#xff0c;首屏加载时的白屏时间&#xff08;也称为首屏等待时间&#xff09;仍然可能存在&#xff0c;尤其在网络条件较差或页面内容复杂…