递归算法_字符串反转_20230412

递归算法-字符串反转

  1. 前言

递归算法对解决重复的子问题非常有效,字符串反转也可以用递归算法加以解决,递归算法设计的关键是建立子问题和原问题之间的相关性,同时需要确立递归退出的条件;如果递归退出的条件无法确定,那么就会出现爆栈的错误(stack overflow)。

  1. 问题描述

给定某个字符串,word=“hello”,通过递归算法实现反转,输出"olleh"字符串。对于递归算法的实现,可以有两种不同的思路,其一是创建一个新的字符串变量,用于保留反转后的字符串;其二是对原字符串直接进行反转,无需借助新的字符串变量。

  1. 子问题分析和递归结束结束条件

对于字符串word=“hello”,其子问题可以通过不断降低字符串长度,从而减低字符的数量。对于字符串word,我们可以构建如下子问题,

word=“hello” 作为原始问题,

word="ello"作为第一个子问题,

word="llo"作为子问题的子问题,

word="lo"作为子问题的子问题的子问题,

word="o"作为子问题的子问题的子问题的子问题–递归结束条件;

word=""空串–递归结束条件

通过上面分析,我们可以选择空串作为递归结束条件,或者选择长度为1的串作为递归结束条件。对于问题描述当中提到两种不同思路,它们分别采用不同的递归结束条件,其中一个方法选择空串作为结束条件,原地反转选择长度为1的子串作为递归的结束条件。

  1. 借助全新字符串变量的递归算法

设计递归函数f(char *word, char *reversal_word, int *i),三个变量分别代表原始字符串,反转后的字符串以及记录反转字符串的下标i.

过程中,我们利用word变为空串时候作为结束条件,在递归返回的时候,提取当前word的首字符,然后保存到reversal_word的第i个字符地址中。

为了更方便理解递归过程,采用图示的方式辅助理解,递归永远都是有去有回,这是由栈的性质决定的,因为程序执行的过程有入栈就必须有出栈,只有这样程序才能完整执行。

在这里插入图片描述

当遇到空字符的时候,这时候递归需要结束,开始返回,代表开始出栈的过程。

在这里插入图片描述

出栈过程中,我们利用word的当前状态,对reversal_word[i]赋值当前的word[0],最终完成源字符串的反转。

  1. 借助全新字符串变量的递归代码实现

递归的过程非常简单,每次把word的指针往前推进1,直至遇到空字符,然后进行回退。

//*i will be set 0 as intial value
void reverse_word(char *word, char *reversal_word, int *i)
{
    char ch;

    if(*word=='\0')
    {
       return;
    }
    else
    {
        reverse_word(word+1,reversal_word,i);
        reversal_word[(*i)++] = *(word + 0);
    }
}

在递归过程中,很容易出现一类错误的算法,这里需要提别提醒,希望引起大家的注意,假定把递归体里面的代码更新成如下格式,好像没有什么错误,但是返回的reversal_word的结果为{‘\0’,‘o’,‘l’,‘l’,‘e’,‘\0’}仔细分析过程,从C语言角度理解,因为首字符为’\0’,它等同于空串。

为什么会出现这种情况呢? 其实道理很简单,原因在于每次word的回退,它其实都提前了一个节拍,因为在递归前word的值已经发生改变,正确的递归中,word+1只是把指针往前推进一步(具体为sizeof(char)字节),但是当word回退的时候,其word的值仍然和递归入口 处的值保持一致。

else
{
    	word=word+1;
		reverse_word(word,reversal_word,i);
        reversal_word[(*i)++] = *(word + 0);
}
  1. 自身反转的递归算法

字符串反转,如果不考虑保留原来的字符串,可以借助字符串本身,对其收尾字符进行有效交换,从对原有字符串完成反转。具体原理就是中间字符视作支点,完成两端字符的交换,这个过程可以借助递归完成。其递归的出口是对字符串的长度进行相应的判断,如果长度减少到1,那么就可以出栈,递归可以掉头返回。

具体来看一下示意图,过程中完成三步操作,在指针往前移动之前,先保留指针指向的字符,然后再交换首字符和末端字符,最后把当前的尾字符赋值为空’\0’,一切完成后,把指针往前推进一步。后面不断重复上面的步骤,直至字符串的长度为1,开始回退(递归出口)

入栈过程

在这里插入图片描述

出栈过程

在这里插入图片描述

  1. 自身反转的代码实现

    当字符串的长度等于1的时候,也就是已经到了原字符串的支点,这个点就是递归的出口,如果再继续反转下去,那么过程结束的时候,又回到原有的状态。

    这个过程中,ch保留首字符是代码成功实现的关键,当递归回退的时候,我们需要利用到递归前保留的ch首字符值,值得一提的是,每个递归中ch属于不同的变量地址,这一点非常关键;另外对于len的长度值的保留的道理也一样,每个递归中的len都属于不同的变量地址。

void reverse_word_2(char *word)
{
    int len;
    char ch;

    len=strlen(word);

    if(len<=1)
    {
        return;
    }
    else
    {
        ch=*(word+0);
        *(word+0)=*(word+len-1);
        word[len-1]='\0';

        reverse_word_2(word+1);

        word[len-1]=ch;

        return;
    }
}
  1. 小结

大量数据结构和算法的实现都依赖递归,无论是深度优先搜索(DFS)还是动态规划(Dynamic programming),其算法的实现都与递归息息相关。本文采用两种不同的思路,借助递归算法对字符串完成反转,更清晰理解了递归的具体过程和基本原理。

其实递归的本质就是分而治之,大事化小,小事化了,从最基础的子问题倒退建立解的过程。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

说过的话就一定要办到 - redo日志

一、什么是redo日志&#xff1f; 如果我们只在内存的 Buffer Pool 中修改了页面&#xff0c;假设在事务提交后突然发生了某个故障&#xff0c;导致内存中的数据都失效了&#xff0c;那么这个已经提交了的事务对数据库中所做的更改也就跟着丢失了&#xff0c;这会导致事务会失去…

4.基于多目标粒子群算法冷热电联供综合能源系统运行优化

4.基于多目标粒子群算法冷热电联供综合能源系统运行优化《文章复现》 相关资源代码&#xff1a;基于多目标粒子群算法冷热电联供综合能源系统运行优化 基于多目标算法的冷热电联供型综合能源系统运行优化 考虑用户舒适度的冷热电多能互补综合能源系统优化调度 仿真平台:matl…

Segment Anything论文翻译,SAM模型,SAM论文,SAM论文翻译;一个用于图像分割的新任务、模型和数据集;SA-1B数据集

【论文翻译】- Segment Anything / Model / SAM论文 论文链接&#xff1a; https://arxiv.org/pdf/2304.02643.pdfhttps://ai.facebook.com/research/publications/segment-anything/ 代码连接&#xff1a;https://github.com/facebookresearch/segment-anything 论文翻译&…

性能测试,python 内存分析工具 -memray

Memray是一个由彭博社开发的、开源内存剖析器&#xff1b;开源一个多月&#xff0c;已经收获了超8.4k的star&#xff0c;是名副其实的明星项目。今天我们就给大家来推荐这款python内存分析神器。 Memray可以跟踪python代码、本机扩展模块和python解释器本身中内存分配&#xf…

VR全景展示,VR全景平台,助理全景展示新模式

引言&#xff1a; VR全景展示是一种新型的展示方式&#xff0c;它利用虚拟现实技术和全景拍摄技术&#xff0c;使参观者可以身临其境地进入虚拟展览空间。这种展示方式不仅能够提供更加沉浸式的参观体验&#xff0c;还可以解决传统展览所面临的时间和地域限制等问题。 VR全景展…

测试工具之JMH详解

文章目录 1 JMH1.1 引言1.2 简介1.3 DEMO演示1.3.1 测试项目构建1.3.2 编写性能测试1.3.3 执行测试1.3.4 报告结果 1.4 注解介绍1.4.1 BenchmarkMode1.4.2 Warmup1.4.3 Measurement1.4.4 Threads1.4.5 Fork1.4.6 OutputTimeUnit1.4.7 Benchmark1.4.8 Param1.4.9 Setup1.4.10 Te…

leetcode 812. 最大三角形面积

题目 给你一个由 X-Y 平面上的点组成的数组 points &#xff0c;其中 points[i] [xi, yi] 。从其中取任意三个不同的点组成三角形&#xff0c;返回能组成的最大三角形的面积。与真实值误差在 10-5 内的答案将会视为正确答案。 示例 1&#xff1a; 输入&#xff1a;points [[…

ActiveReportsJS 4.0 FIX ActiveReportsJS 4.0 Crack

JavaScript 报告工具是一组用于数据整合和可视化的 Web 组件。ActiveReportsJS 是前端开发人员用来在 Web 应用程序中嵌入报告的解决方案。报表设计器和查看器组件、强大的数据可视化器和丰富的 API 等主要功能使 ActiveReportsJS 成为行业领导者。 JavaScript 报告引擎 利用强…

Spark SQL join操作详解

一、 数据准备 本文主要介绍 Spark SQL 的多表连接&#xff0c;需要预先准备测试数据。分别创建员工和部门的 Datafame&#xff0c;并注册为临时视图&#xff0c;代码如下&#xff1a; val spark SparkSession.builder().appName("aggregations").master("lo…

Python进阶内容--迭代器和生成器

什么是迭代器 在 Python 中&#xff0c;迭代器&#xff08;Iterator&#xff09;是一个访问集合元素的对象&#xff0c;它能够实现遍历集合的所有元素&#xff0c;而无需了解集合底层结构和细节。Python 中所有可迭代的对象&#xff08;如 列表、元组、字符串、字典、集合等&a…

leetcodeTmp

文章目录 39. 组合总和33. 搜索旋转排序数组153. 寻找旋转排序数组中的最小值49. 字母异位词分组53. 最大子数组和55. 跳跃游戏56. 合并区间62. 不同路径 39. 组合总和 39. 组合总和 DFS排列&#xff1a;每个元素可选0次&#xff0c;1次以及多次 public List<List<Int…

元宇宙:虚拟仿真技术的全面提升

在当今数字化的世界中&#xff0c;我们经常听到虚拟现实、增强现实、混合现实等技术的名词&#xff0c;这些技术的应用越来越成熟。其中&#xff0c;虚拟仿真技术是一种通过计算机技术来模拟实际场景和对象的过程&#xff0c;它为我们提供了更多的可能性。而最近备受瞩目的元宇…

加密的本质:数学的不对称性

文章目录 引言I 预备知识1.1 加密和授权1.2 非对称的特性II 椭圆曲线加密的方法2.1 椭圆曲线2.2 椭圆曲线的性质引言 不对称有时却自有其妙处与美感,比如黄金分割就是不对称的。 可以通过加密和授权,兼顾保护信息不外泄,而且某些得到授权的人还能使用信息。 I 预备知识 …

亚马逊云科技为全球的可持续发展进程做出贡献

可持续发展是一个涉及经济、环境和社会三个方面的复杂问题。经济发展必须在保护环境和社会公正的前提下进行&#xff0c;这样才能实现真正的可持续发展。为了实现这一目标&#xff0c;人们需要借助技术手段&#xff0c;更好地理解和解决环境和社会问题。 亚马逊云科技是全球领…

(大数据开发随笔9)Hadoop 3.3.x分布式环境部署——全分布式模式

索引 完全分布式模式守护进程布局集群搭建准备总纲配置文件格式化集群启动集群 集群控制命令集群启停进程查看启动日志查看集群常见问题 案例演示&#xff1a;WordCount 完全分布式模式 分布式文件系统中&#xff0c;HDFS相关的守护进程也分布在不同的机器上&#xff0c;如&am…

tp5实现导入excel表到数据库

hello&#xff0c;大家好&#xff0c;好长时间没有更新文章了。最近一直在忙着做项目。所以断更了。 那么好&#xff0c;各位老铁是否想要实现导入导出的功能 请关注我&#xff0c;解密如何实现导入导出&#xff0c; 那么今天先来讲一下用thinkphp5.0 如何实现Excel表格导入数据…

js 事件流程

描述 JavaScript 的执行是单线程的&#xff0c;后面的任务需要等待前面的任务完全完成后&#xff0c;再去执行。DOM 事件&#xff08;文件的加载等&#xff09;、定时器、网络请求等事件&#xff0c;并不会消耗 CPU&#xff0c;这些事件无需等候&#xff0c;所以出现了异步。主…

【Unity VR开发】结合VRTK4.0:创建一个按钮(Option Button)

语录&#xff1a; 如同天上降魔主&#xff0c;真是人间太岁神。 前言&#xff1a; 选项按钮是一种提供多项选择选项的方法&#xff0c;其中只有一个按钮可以处于激活状态&#xff0c;激活另一个按钮时将确保组中的所有其他按钮都已停用。我们可以使用嵌套在预制件中的预制件来实…

C++命名空间域namespace与域作用限制符: :,cin,cout输入输出简单介绍

TIPS C是在C的基础之上&#xff0c;容纳进去了面向对象编程思想&#xff0c;并增加了许多有用的库&#xff0c;以及编程范式等C总计63个关键字&#xff0c;C语言32个关键字&#xff0c;具体没有必要先不去管它 域&#xff0c;命名空间域与namespace关键字 cpp需要解决的第一…

数据库中的视图及三级模式结构

文章目录 一、视图二、数据库三级模式结构 一、视图 简单地说&#xff0c;视图可以看成是一个窗口&#xff0c;它所反映的是一个表或若干表的局部数据&#xff0c;可以简化查询语句。视图一经定义&#xff0c;用户就可以把它当作表一样来查询数据。 但视图和基本表不同&#…