【刷题】初探递归算法 —— 消除恐惧

在这里插入图片描述

送给大家一句话:
有两种东西,
我对它们的思考越是深沉和持久,
它们在我心灵中唤起的惊奇和敬畏就会日新月异,
不断增长,
这就是我头上的星空和心中的道德定律。
-- 康德 《实践理性批判》

初探递归算法

  • 1 递归算法
  • 2 Leetcode 面试题 08.06. 汉诺塔问题
    • 题目描述
    • 算法思路
  • 3 Leetcode 21. 合并两个有序链表
    • 题目描述
    • 算法思路
  • 4 Leetcode 206. 反转链表
    • 题目描述
    • 算法思路
  • 5 Leetcode 24. 两两交换链表中的节点
    • 题目描述:
    • 算法思路
  • 6 Leetcode 50. Pow(x, n)
    • 题目描述
    • 算法思路
  • 7 总结
  • Thanks♪(・ω・)ノ谢谢阅读!!!
  • 下一篇文章见!!!

1 递归算法

在解决一个规模为 n 的问题时,如果满足以下条件,我们可以使用递归来解决:

  1. 问题可以被划分为规模更小的子问题,并且这些子问题具有与原问题相同的解决方法。
  2. 当我们知道规模更小的子问题(规模为 n-1)的解时,我们可以直接计算出规模为 n 的问题的解。
  3. 存在一种简单情况,或者说当问题的规模足够小时,我们可以直接求解问题。这里一般成为函数出口(非常重要)

一般的递归求解过程如下:

  1. 验证是否满足简单情况
    简单情况是指问题规模非常小,通常可以直接得到答案的情况。我们需要首先检查当前问题是否满足这种情况。

  2. 假设较小规模的问题已经解决,解决当前问题
    在递归中,我们假设已经解决了规模较小的子问题,然后基于这些子问题的解来构建当前问题的解。这种假设称为“递归假设”。

总结来说,递归代码的编写如同使用一个“黑盒”一样,我们需要相信递归调用会正确解决子问题,而我们只需要关注处理当前的问题。

下面我们通过一个具体实例来展示如何在实践中解决问题:

假设我们要计算斐波那契数列中的第 n 项。斐波那契数列的定义如下:
F ( 0 ) = 0 \text{F}(0) = 0 F(0)=0
F ( 1 ) = 1 \text{F}(1) = 1 F(1)=1
对于 n ≥ 2 n \geq 2 n2 F ( n ) = F ( n − 1 ) + F ( n − 2 ) \text{F}(n) = \text{F}(n-1) + \text{F}(n-2) F(n)=F(n1)+F(n2)

在这个问题中:
简单情况是 F ( 0 ) \text{F}(0) F(0) F ( 1 ) \text{F}(1) F(1),我们可以直接得到答案。
对于其他情况,我们假设 F ( n − 1 ) \text{F}(n-1) F(n1) F ( n − 2 ) \text{F}(n-2) F(n2) 已经计算出来,然后通过 F ( n ) = F ( n − 1 ) + F ( n − 2 ) \text{F}(n) = \text{F}(n-1) + \text{F}(n-2) F(n)=F(n1)+F(n2) 计算出 F ( n ) \text{F}(n) F(n)

这种递归解决问题的方法非常强大,但也需要注意避免过度递归带来的性能问题,比如栈溢出或时间复杂度过高等。

接下来我们一起来解决问题吧!!!

2 Leetcode 面试题 08.06. 汉诺塔问题

上连接: 面试题 08.06. 汉诺塔问题

题目描述

在这里插入图片描述
汉诺塔是个非常有意思的问题,其典故更是神乎其神:

法国数学家爱德华·卢卡斯曾编写过一个印度的古老传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔。不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针上,小片必须在大片上面。僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,而梵塔、庙宇和众生也都将同归于尽。

题目给我们了xyz三个容器模拟柱子,我们需要模拟实现移动的过程,将X容器中的盘子移动到Z中。

算法思路

乍一看我们想不到什么思路,所以我们先来画图分析一波:
在这里插入图片描述

通过这三种情况我们就能分析出来,这道题可以被拆分成许多子问题来解决:

如果想要移动n个盘子

  1. 先把 n - 1 个盘子移到中转柱子上,再把第n个移到目标柱子上。
  2. 接下来处理 这n - 1 个盘子,把 n - 2 个小盘子移到中转柱子上,第 n - 1个移动到目标柱子上。
  3. 重复 1 2 直到解决问题…

注意

    // x 为当前柱子 y 为中转柱子 z 为目标柱子 //我们只需要注意解决当前的问题,子问题交给黑盒处理void dfs(vector<int>& x, vector<int>& y, vector<int>& z , int n ){   //递归出口if(n == 1){int tmp = x.back();z.push_back(tmp);x.pop_back();return ;}//将 n 个盘子从 X 转移到 Z //则先把 n-1个盘子移到 Ydfs(x , z , y , n - 1);//然后此时X只有一个最大的盘子, 移到Zint tmp = x.back();z.push_back(tmp);x.pop_back();//现在 Y 上有 n-1 个盘子继续进行移动到Z上dfs(y , x , z , n - 1);return ;}void hanota(vector<int>& A, vector<int>& B, vector<int>& C) {int n = A.size();dfs(A , B , C , n);return ;}

提交:过啦!!!

3 Leetcode 21. 合并两个有序链表

上连接!家人们:21. 合并两个有序链表

题目描述

在这里插入图片描述
很好理解的题目!

算法思路

相信大家看到这个题,肯定有迭代循环思路,但是今天我们通过递归来解决问题:
在这里插入图片描述

我们首先分析一下:

  • 当前问题:当我们处理当前情况时,我们需要把后续处理交给黑盒,我们需要的是将较小的节点插入到新链表中
  • 子问题:处理除去以被处理的“较小的节点”之外的链表节点,使其合并。
  • 函数出口:当我们处理到两个链表都为空时直接返回,或者一方为空直接返回另一链表即可!
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {//处理为空的情况if(l1 == nullptr) return l2;if(l2 == nullptr) return l1;//都不为空,选择较小值进行插入!!!if(l1->val < l2->val){//l1 小 就把它的next交给黑盒处理l1->next = mergeTwoLists(l1->next , l2);//然后将它返回(这样黑盒才可以获取当前节点的next节点)return l1;}else{//l2 小 就把它的next交给黑盒处理l2->next = mergeTwoLists(l1 , l2->next);return l2;}}

提交:过啦!!!

4 Leetcode 206. 反转链表

上链接: 206. 反转链表 !

题目描述

在这里插入图片描述
同样很好理解,接下来我们来使用递归解决问题

算法思路

首先这道题需要注意的一点是:我们要先找到新链表的头(即当前链表的尾节点)黑盒的返回值设置为新链表的头,然后再来进行反转。就类似二叉树的后序遍历。我们不能从链表的头开始反转到尾(先序遍历)。因为这样就无法获取新链表的头结点了

从宏观来看:我们只需要处当前问题:

  1. 子问题: 后续节点的反转!黑盒会返回我们的头结点。我们的黑盒一定可以帮助我们解决后序的节点的反转。
  2. 当前问题:把当前节点插入到以被反转的链表后,把当前节点的next设置为空即可!
  3. 函数出口:当走到链表结尾即为出口!
ListNode* reverseList(ListNode* head) {//寻找新的头结点if( head == nullptr || head->next == nullptr ) return head;ListNode* newhead = reverseList(head->next);//进行倒置head->next->next = head;//next设置为空head->next = nullptr;//返回新链表的头return newhead;}

提交:过啦!!!

5 Leetcode 24. 两两交换链表中的节点

跟上节奏:24. 两两交换链表中的节点 !!!

题目描述:

在这里插入图片描述
题目也很好理解奥

算法思路

我们依旧是使用递归来解决:

  1. 当前问题:置换两个节点,并指向后续以及置换完成的链表。
  2. 子问题:后序节点的置换
  3. 函数出口:为空或只有一个节点之间返回即可。
    ListNode* swapPairs(ListNode* head) {//利用递归解决问题//一次要处理两个节点if(head == nullptr) return nullptr;if(head->next == nullptr) return head;//继续处理 --- 相信 swapPairs(tmp) 这个会处理好剩余部分ListNode* tmp = swapPairs(head->next->next);//进行处理//记录下 1 2 节点的后面的2节点,它是置换后的头节点。ListNode* ret = head->next;//置换head->next->next = head;head->next = tmp;return ret;}

提交:过啦!!!

6 Leetcode 50. Pow(x, n)

最后一题:50. Pow(x, n) !!!

题目描述

在这里插入图片描述
这道题需要我们使用幂函数,当然不是一般的循环相乘(必然超时),我们要实现快速幂!

算法思路

快速幂的思想很简单:假如我们需要 210 ,我们就求25 ,求 25 就求 22 * 22 * 2 …以此类推直到次数为 0 就返回 1

需要注意的是负数的处理,求负次幂,我们可以先求正的然后在取倒数。
还有边界的处理,题目所给的最小值 - 231 取正后为 231,超出int的范围,所以需要转换为long long

    double myPow(double x, long long n) {if(n == 0) return 1;if( n < 0 ) {long long t = (long long)(-n);double tmp = myPow( x , t / 2);return t % 2 == 0 ? 1 / (tmp * tmp) : 1 / (tmp * tmp * x);}else{double tmp = myPow( x ,  n / 2);return n % 2 == 0 ? tmp * tmp : tmp * tmp * x;}}

提交过啦!!!

7 总结

我们进行递归算法,只需要处理好当前问题,其余相信我们的黑盒可以解决。注意:

  1. 函数出口的设置,这个是关键!!!
  2. 返回值的设置要合适,看题分析!!!

Thanks♪(・ω・)ノ谢谢阅读!!!

下一篇文章见!!!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

我给线程池管理框架hippo4j找bug

1 虚拟机参数不生效 hippo4j的docker启动脚本位于 docker/docker-startup.sh 。从下图可以看到 JAVA_OPT放在了jar包名 hippo4j-server.jar之后&#xff0c;而只有项目参数才放在jar包名之后。 实际上这里JAVA_OPT中包含虚拟机参数&#xff0c;而虚拟机参数要放在jar包名之前…

前端之HTML语言(持续更新)

前端之HTML语言 学习完后端的各种层之后&#xff0c;今天开始学习前端&#xff0c;前端和后端都是一个项目的组成部分。 前端对应得到语言是HTML&#xff0c;HTML最重要的有三块&#xff0c;行为&#xff0c;样式&#xff0c;J结构。行为就是交互&#xff0c;理解为鼠标的点击…

【多模态】34、LLaVA-v1.5 | 微软开源,用极简框架来实现高效的多模态 LMM 模型

文章目录 一、背景二、方法2.1 提升点2.2 训练样本 三、效果3.1 整体效果对比3.2 模型对于 zero-shot 形式的指令的结果生成能力3.3 模型对于 zero-shot 多语言的能力3.4 限制 四、训练4.1 数据4.2 超参 五、代码 论文&#xff1a;Improved Baselines with Visual Instruction …

Xcode下载安装

1.Xcode可用版本判断&#xff1a; 2.Xcode下载安装&#xff1a; 方案1:AppStore 下载更新 若方案1失败则 方案2:指定版本Xcode包下载解压安装 苹果下载 3.Xcode命令行工具插件安装 xcode-select --install 备注&#xff1a; xcode_x.x.x.xip(压缩包存在时效性(使用前24h/…

20 VUE学习:插件

介绍 插件 (Plugins) 是一种能为 Vue 添加全局功能的工具代码。下面是如何安装一个插件的示例&#xff1a; import { createApp } from vueconst app createApp({})app.use(myPlugin, {/* 可选的选项 */ })一个插件可以是一个拥有 install() 方法的对象&#xff0c;也可以直接…

计算一个3x3矩阵对角线和其它两条线的元素之和

计算一个3x3矩阵对角线和其它两条线的元素之和 #include <stdio.h> int main () { int d0,b0,s,i,j; int a[3][3]{1,2,3,4,5,6,7,8,9}; for(i0,j2;i<3;i,j--) dda[i][i]a[i][j]; for(i0,j0;i<3;) {bba[i][j]a[i][j2]; ii2;} sdb; printf("d%d\nb%d\ns%d\n&qu…

支付宝支付(沙盒支付)

后端页面代码 Controller RequestMapping("/pay") public class PayController {private String orderId;Autowiredprivate OrdersService ordersService;Value("${appId}")private String appId;Value("${privateKey}")private String private…

ReDos攻击浅析

DOS为拒绝服务攻击&#xff0c;re则是由于正则表达式使用不当&#xff0c;陷入正则引擎的回溯陷阱导致服务崩溃&#xff0c;大量消耗后台性能 正则 ​ 探讨redos攻击之前&#xff0c;首先了解下正则的一些知识 执行过程 大体的执行过程分为: 编译 -> 执行编译过程中&…

牛客热题:缺失的第一个正整数

牛客热题&#xff1a;数组中出现一次的两个数字> &#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;力扣刷题日记 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 文章目录 …

SPWM载波调制方式-三电平杂记1

方法一&#xff1a; P2 O1 N0 方法二&#xff1a;双载波直接发波 方法三&#xff1a;负轴载波和调制波往上抬升1&#xff0c;得到使用同一个载波 在正半周在P和O切换&#xff0c;在下半轴式O和N切换

出现 Transaction rolled back because it has been marked as rollback-only 解决方法

目录 1. 问题所示2. 原理分析3. 解决方法1. 问题所示 用户反馈的Bug如下所示: Transaction rolled back because it has been marked as rollback-only截图如下: 浏览器终端同样显示: 2. 原理分析 错误表明,在事务的生命周期内,遇到了某个异常或条件,导致该事务被标记…

四川古力未来科技抖音小店安全靠谱,购物新体验

在数字化浪潮席卷而来的今天&#xff0c;电商行业蓬勃发展&#xff0c;各种线上购物平台如雨后春笋般涌现。其中&#xff0c;抖音小店凭借其独特的短视频直播购物模式&#xff0c;迅速赢得了广大消费者的青睐。而四川古力未来科技抖音小店&#xff0c;更是以其安全靠谱、品质保…

注解的妙用

一、注解是什么&#xff1f; 在Java中&#xff0c;注解&#xff08;Annotation&#xff09;是一种用于在代码中插入元数据的方式。注解不直接影响程序代码的行为&#xff0c;而是提供了一种形式化的方法来说明代码的某些方面&#xff0c;供编译器、开发工具或运行时环境等使用…

Vue+AntDesignVue实现a-tree树形组件的层级选中功能

文章目录 一、构建树形组件二、js代码实现 最近碰到了一个新需求&#xff0c;使用树形选择器实现角色管理功能&#xff0c;当用户选中一个节点时&#xff0c;其所有子节点都会被自动选中&#xff1b;同样&#xff0c;当用户取消选中一个节点时&#xff0c;其所有子节点也会被取…

LNMP部署及应用

目录 1.LNMP概述 Nginx 特点 Nginx 作用 2.分布式部署LNMP操练 Nginx主机&#xff1a;CentOS 7-1 PHP主机: CentOS 7-2 1.LNMP概述 Nginx 是开源、高性能、高可靠的 Web 和反向代理服务器&#xff0c;而且支持热部署&#xff0c;几乎可以做到 7 * 24 小时不间断运行&…

Java实战:文本文件复制

任务目标 本实战任务的目标是创建一个Java程序&#xff0c;用于复制指定的文本文件到另一个位置&#xff0c;并在控制台中显示复制结果。 任务步骤 创建源文件&#xff1a;在指定的路径D:\love.txt创建源文件。创建文件复制类&#xff1a;在net.huawei.student.test包中创建…

绿联 安装memcached容器 - 一个开源的高性能分布式内存对象缓存系统

绿联 安装memcached容器 - 一个开源的高性能分布式内存对象缓存系统 1、镜像 memcached:latest 2、安装 2.1、基础设置 重启策略&#xff1a;容器退出时总是重启容器。 2.2、网络 网络选择桥接(bridge)。 2.3、端口设置 容器端口11211固定不变&#xff0c;本地端口若未被…

即时通讯视频会议平台,WorkPlus本地化部署解决方案

随着现代科技的快速发展&#xff0c;传统的会议方式已经不再满足企业和组织的需求。即时通讯视频会议以其便利性和高效性&#xff0c;成为了现代企业沟通和协作的重要工具。通过即时通讯视频会议&#xff0c;企业可以实现无时差的交流和远程协作&#xff0c;增强团队合作和提高…

计算机系统结构之虚拟存储器

虚拟存储器通过增设地址映像表机构来实现程序在主存中的定位。 一、段式管理 (1)段式管理的基本思想是把程序按内容或过程函数关系分成段&#xff0c;每段有自己的名字。一个用户作业或进程所包含的段对应一个二维线性虚拟空间&#xff08;二维虚拟存储器&#xff09;。段式管…

springboot实现文件上传功能,整合云服务

文章目录 这是springboot案例的,文件上传功能的拆分,本篇将带大家彻底了解文件上传功能,先从本地存储再到云存储,全网最详细版本,保证可以学会,可以了解文件上传功能的开发文件上传功能剖析进行书写一个小的文件上传文件上传的文件三要素首先表单提交的方式要是 post方式,第二个…