字符串反转,神奇的算法-读《编程珠玑(第二版)》

旋转字符串;编程珠玑第二章;rotate a one-dimensional vector;循环移位数组;编程之美 一:问题描述: 编程珠玑第二章的第二个问题是字符串(或者理解为向量)旋转问题,具体描述如下: rotate a one-dimensional vector of n elements left by i positions. eg: with n = 8; i = 3, the vector abcdefgh is rotated to defghabc. 这个问题在编程之美中也出现了,问题描述: 设计一个算法,把一个含有N个元素的数组循环右移K位,要求时间复杂度为O(N),且只允许使用两个附加 阅读详情

最近在缓慢地读《编程珠玑(第二版)》(英文名Programming Pearls),书很薄(正文才160多页),但正如其封面“近20年来众多大师级程序员一致推崇的作品”所示,这本经典哪能是我一下子就能读完的?书中有很多简洁但有趣的例子分析,更有作者的实际经验及注意点的阐述,值得一点点地读,一遍不够以后再来第二、三遍...

另外,前些天发现51CTO读书频道有《编程珠玑(续)》(英文名 More Programming Pearls)整本书的在线阅读,真是太赞了!

回到正题。第二章“啊哈!算法”中作者给出三个“小题目”,其中第二个是:将一个具有n个元素的一维向量x向左旋转i个位置。例如,将 ABC123DEF456 向左旋转 3 个位置之后得到 123DEF456ABC。要求是花费与n成比例的时间来完成这个操作。

题目虽小,但正如本章标题“啊哈!算法”所示,作者想要强调的是算法的巧妙与强大,其中有本题的3种解决方案。

*.使用临时数组

这大概是大多数人都会想到的一种方案,即将所给向量x的前i个复制到临时数组中,再将剩下的n-i 个元素往左移动i个位置,最后将临时数组中的i个元素复制回x中后面的位置。

代码实现:

 
  1. public void tempArrReverse(char [] arr, int len, int m){
  2. char [] temp = new char[m];
  3. // 将数组前m个元素保存到临时数组
  4. for(int i = 0; i < m; i++){
  5. temp[i] = arr[i];
  6. }
  7. // 将数组后面(len-m)个元素前移
  8. for(int i = m; i < len; i++){
  9. arr[i-m] = arr[i];
  10. }
  11. // 将临时数组所有元素复制到原数组
  12. for(int i = 0; i < m; i++){
  13. arr[len-m+i] = temp[i];
  14. }
  15. }

很明显上面的解法虽然简单移动,但用到了i个额外的空间,比较浪费空间。于是又有一个作者称赞“堪称巧妙的杂技表演”的解法。

*.“巧妙的杂技表演”

先将x[0]移到临时变量t中,再把x[i]移到x[0]腾出来的位置中,x[2i]移到x[i]中,以此类推(每一次移动时将x[]中的下标对其长度n取模),直到又回到从x[0]提取元素,此时应该把临时变量t放入到上一个位置中,并开始下一次迭代,即对x[1]进行类似的操作。

找来书中直观的图如下:

代码实现:

 
  1. public void juggleReverse(char [] arr, int len, int m){
  2. int k = 0;
  3. for(int i = 0; i < m; i++){
  4. k = 1; //每次迭代都从1倍位移开始
  5. char temp = arr[i];
  6. while((k*m+i) % len != i){
  7. arr[(k-1)*m+i] = arr[k*m+i];
  8. k++;
  9. }
  10. arr[(k-1)*m+i] = temp;
  11. }
  12. }


但是,正如作者所提醒的“将这个想法转换为代码,请务必小心!”实际上我的实现中只能是当原向量长度n是位移i的整数倍时才可行,碰巧书中的也是用 i=3,n=12 这个例子来演示说明的,而且感觉此处的译文有点儿别扭,理解得不顺畅,得找找原文是怎么说的。

如果你在纸上画一下不是整数倍的情况,会发现其实情况复杂得多,有可能某些元素被放到其正确位置的后面去了,而我又不想用很多if...else语句来判断所出现的情况,因为我认为是我没理解到作者的思路,所以暂时只能这么实现(还要再思考),希望高手看到能指教一下。=)

*.另一种更巧妙的思路-原语的力量

其实题目的意思就是字符串反转(reverse,不知道原文中“旋转”是不是这个词,得查证),书中这一小节“原语的力量”提到“有些编程语言提供了旋转作为对向量的原语运算”。假如已经有将数组指定部分元素进行反转的函数(原语操作),接下来的解法就更有意思了。

原问题可以这样来看:将原数组看成 ab,需要转换成 ba,先单独对子数组a进行反转得到a'b(a'表示a反转后的结果),同理单独反转b,得到 a'b',最后将得到的 a'b' 一起进行一次反转可得 (a'b')',而这就是最终结果 ba了,不信你在纸上尝试一下(或者请看下面更有趣的、可操作的例子)。

代码实现:

 
  1. // 原语操作-反转数组
  2. public void reverse(char [] arr, int start, int end){
  3. int mid = (start + end) / 2;
  4. for(int s = start, i = 1; i < mid; s++, i++){
  5. char temp = arr[s];
  6. arr[s] = arr[end-i];
  7. arr[end-i] = temp;
  8. }
  9. }
  10. public void useReverse(char [] arr, int len, int m){
  11. reverse(arr, 0, m);
  12. reverse(arr, m, len);
  13. reverse(arr, 0, len);
  14. }

其实到这里我认为作者已经让我感受到算法巧妙之处了,对于相同问题的不同理解、看法可以激发出这么精彩的解法。但实际上你还会发现这本经典书还很频繁地列举其他大师级人物对某问题的解法与运用之类的历史信息。例如,书中提到 Ken Thompson也是将这段代码用在其编辑器和转置代码的,而且“声称即使在那个时候,那也可编入神话故事了”。难道还不够精彩吗?请看下面。

*.可操作的证明方法-手摇法

如果要将一个具有10个元素(我们只有10个手指啊)的数组向上旋转5个位置,先让两只手的掌心正对你自己,左右放在右手上面(其实两只手是同意平面上的),看下图:

其实如果亲自读这本书的话,会发现更多精彩!这样一本书,难道不值得一点点地读吗?

 

转自:http://haolloyin.blog.51cto.com/1177454/560597

 

 

 

 

《编程珠玑》中的最优性能效率最高字符串反转算法 立即下载

相关推荐

基于PLC的冲压件自动生产线电气系统设计【附数据】

考虑到生产线的高效运行和维护简便性,选择了三菱FX系列的可编程逻辑控制器(PLC)作为核心控制单元,该型号的PLC因其高可靠性和强大的功能集,在工业自动化领域有着广泛的应用。最后,在完成初步的软件开发后,进行了多轮次的模拟测试和现场调试,逐步修正了存在的问题,最终达到了预期的功能要求。例如,对于进料环节,选用了光电传感器以精确检测物料的位置;此外,为了适应不同尺寸的工件加工需求,还特别设计了一套可调节的夹具系统,不仅提高了生产线的灵活性,同时也降低了更换模具的成本。✅ 感恩科研路上每一位志同道合的伙伴!

lagougongzuoshi的博客 1292

《编程珠玑2》读书笔记1---翻转代码

第二章 ”啊哈,算法“ P11 问题B:将一个n元一维向量向左旋转i个位置(循环移位),例如abcdefgh左循环移位3个位置变成defghabc  要求:使用一个n元的中间向量在n步内完成,能否仅适用数十个额外字节的存储空间,在正比于n的时间内完成? "啊哈,灵机一动": 贴个照片,不侵权吧,呵呵,手我加了指甲,分辨手掌正反面 代码: package org.

On the way 725

车载LIN总线避坑指南:主从节点通信失败的5个常见原因及解决方案

本文深度解析车载LIN总线主从节点通信失败的五大常见原因,涵盖物理层信号异常、调度表冲突、LDF配置错误、节点状态机缺陷及环境干扰。重点剖析了LDF文件配置不一致、波特率不匹配等关键问题,并提供了从示波器波形分析到软件配置检查的完整实战排查路径,帮助工程师高效定位并解决LIN通信故障。

g9h0i1的博客 1249

循环移位(翻转算法)

循环移位

yk_ee的博客 2624

SAP物料分类账(ML)避坑指南:激活顺序错了怎么办?从CKMSTART到差异分摊的完整流程

本文详细解析SAP物料分类账(ML)的正确激活顺序与配置流程,帮助用户避免常见陷阱如'LKW无科目'、'在制品重估失败'等问题。从CKMSTART到差异分摊的完整流程,涵盖关键配置节点、典型报错分析与应急处理方案,确保产品成本控制(CO-PC)模块的顺利运行。

weixin_42524708的博客 258

EtherCAT主站IGH-- 49 -- 搭建xenomai系统及自己的IGH主站

以上就是搭建xenomai系统及自己的IGH主站的内容。有不明白的地方欢迎留言;有建议欢迎留言,我后面编写文档好改进。创作不容,如果文档对您有帮助,记得给个赞。

常驻客栈的博客--嵌入式EtherCAT 3158

编程珠玑字符串反转

编程珠玑真是一本让人感觉到眼前一亮的书,虽然书不厚,但是里面的知识很贴近实际应用,也很有启发性,如果能真正的消化里面的内容,对程序的理解肯定会上一个档次。 本文给出的是第二章习题的第五题的大概程序! #include using namespace std; void move(int * arr, int arrsize,int n);//将数组arr的前n个元素左移 void show(

shiwazone的专栏 1023

TC3XX - MCAL知识点(三十七):AURIX™ TC3xx 的BootLoader烧录APP完成之后跳转使多个核均正常运行

摘要:针对AURIX TC3xx多核芯片在软件复位后仅Core0能启动的问题,分析发现该芯片在Cold Power-on Reset(断电复位)时会完整执行多核启动流程,而Application Reset(软件复位)会跳过从核初始化。解决方案包括:1)在BootLoader中显式调用IfxCpu_startCore()函数启动其他核;2)通过跳转函数强制各核从指定地址启动;3)双Boot场景下让每个核独立响应复位命令。实测表明,软件复位后需手动触发从核启动,或采用断电复位方式确保所有核正常初始化。

梦想技术家 411

对二进制数组进行循环左移C语言,旋转字符串;编程珠玑第二章;rotate a one-dimensional vector;循环移位数组;编程之美...

一:问题描述:编程珠玑第二章的第二个问题是字符串(或者理解为向量)旋转问题,具体描述如下:rotate a one-dimensional vector of n elements left by i positions. eg: with n = 8; i = 3, the vector abcdefgh is rotated to defghabc.这个问题在编程之美中也出现了,问题描述:设计...

weixin_30569303的博客 698

vue - 网站接入微信扫码登录功能详细教程,完整详细流程及完整功能示例源代码(附常见问题的解决方案与二维码样式修改方案)

vue.js项目植入微信登录,vue网页项目怎么做微信扫码登录,VUE项目中的微信扫码登录,VUE中最简单的js调用微信扫一扫功能,vue:如何设计网页的微信扫码登录功能,微信扫码功能官方文档,通过vue方式实现二维码扫码功能,vue调用微信扫码,vue H5 调用微信扫描二维码,Vue前端实现微信扫码登录,vue-wxlogin 微信授权登录组件,网站引入的微信登录框如何修改宽高或其他样式,wxlogin 组件插件怎么改变宽高,vue-wxlogin组件怎么自定义样式,微信网页授权,vue调用微信JSDK

✅ 精选推荐文章 6365

深水区探秘:小红书App x-s参数逆向与高并发爬虫实战(2026版)

在移动互联网的碎片化时代,小红书凭借其“社区+电商”的独特模式,积累了超过3亿月活用户。其内容生态覆盖了从美妆、穿搭到旅行、数码等几乎所有垂直领域。对于数据分析师、市场研究员以及AI算法工程师而言,小红书平台蕴含的价值是巨大的——无论是热门趋势洞察、KOL画像分析,还是多模态图文数据的采集。然而,想要高效、稳定地获取小红书App的公开数据,却并非易事。与Web端相比,小红书App的防护体系堪称“铜墙铁壁”。其核心的反爬机制建立在动态混淆的加密参数之上,尤其是请求头中的X-SX-T以及X-S-Common。

2201_76125261的博客 263

循环字符串问题中的翻手算法

最近再看《编程珠玑》,

玄云飘风的博客 638

一次搞定 SAP IDoc 失败重处理与安全清理:BD87 实战指南

本文介绍了SAP IDoc错误处理的BD87实战指南。主要内容包括: BD87的核心功能:监控IDoc处理状态并支持人工重处理或标记删除,适用于入站/出站IDoc故障处理。 重处理前的关键步骤: 区分技术错误与业务错误 检查是否允许重复处理 确认日期范围设置正确 标准操作流程:通过BD87选择错误IDoc节点执行重处理,特别适用于状态51的应用错误。 标记删除操作:将无用IDoc标记为可清理状态,后续可通过WE11物理删除或归档处理。 常见问题解决方案:包括权限控制、批量处理优化建议以及自动化定位工具的开发

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 452

旋转字符串

一:问题描述: 编程珠玑第二章的第二个问题是字符串(或者理解为向量)旋转问题,具体描述如下: rotate a one-dimensional vector of n elements left by i positions. eg: with n = 8; i = 3, the vector abcdefgh is rotated to defghabc. 这个问题在编程之美中也出现了,...

jackyhungvip的博客 142

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

字符串逆序算法实现

给定一个字符串S,将字符串S中的字符顺序颠倒过来,即实现字符串的逆序。本文将介绍一种字符串逆序算法的实现。

a_woxinfeiyang_a的专栏 3401

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

字符串按特定分隔符反转

阿里巴巴的实习生笔试题,实现将字符串按特定分隔符进行反转,如“www.taobao.com”,反转后为"com.taobao.www",要求时间复杂度为O(n),空间复杂度为O(1). 解题思想:用两个指针记录分隔符之间的子字符串,然后先将子字符串进行反转,逐段全部反转后,再将整个字符串进行一次反转。 [cpp] view plaincopy

likika2012的专栏 1715

旋转交换或向量旋转

问题描述 (来源于《编程珠玑》第2版的第2章第11页问题B) 请将一个具有n个元素的一维向量向左旋转i个位置。例如,假设n=8,i=3,那么向量abcdefgh旋转之后得到向量defghabc。简单编码使用一个具有n个元素的中间向量分n步即可完成此作业。你可以仅使用几十字节的微小内存,花费与n成比例的时间来旋转该向量吗? 解决思路 方案一: 将向量x中的前i个元素复制到一个临时

松子茶的专栏 2321

字符串的替换、反转、查找、分割

以下实例中我们使用 java String 类的 replace 方法来替换字符串中的字符: public class StringReplaceEmp{ public static void main(String args[]){ String str="Hello World"; System.out.println( str.replace( 'H','W...

江江同学的博客啊 401

LeetCode题解(0541):字符串分段反转(Python)

题目:原题链接(简单) 题目标签: 解法 时间复杂度 空间复杂度 执行用时 Ans 1 (Python) O(N)O(N)O(N) O(N)O(N)O(N) 36ms (91.51%) LeetCode的Python执行用时随缘,只要时间复杂度没有明显差异,执行用时一般都在同一个量级,仅作参考意义。 解法一(): def reverseStr(self, s: str, k: int) -> str: ans = "" while k * 2 <= len

长行 616

字符串转置的一种方法

最近看C++课本发现了substr这个神奇的函数,然后就根据这个写了个字符串转置的函数。 #include &amp;lt;string&amp;gt; using std::string; string reverse(const string&amp;amp; str) { if (str.length() == 1) return str; if (str.length() == 2) return str...

weixin_43773570的博客 1688

J-Link驱动签名验证失败?手把手教你搞定Windows 11/10下的WHQL驱动安装(附INF文件下载)

本文详细解析了J-Link驱动在Windows 11/10企业环境中签名验证失败的解决方案,重点介绍了WHQL认证驱动的获取与安装流程,并提供了固件升级和新机调试的实用技巧,帮助开发者高效解决驱动兼容性问题。

weixin_33701251的博客 533

笔试——字符串算法题——翻转分段字符串

这个既然有人笔试完就问,那我还是敲一份分享一下吧。         题目大意:字符串的问题,把字符串按点的位置翻转。要求时间复杂度O(n)、空间复杂度O(1)。                             例如:对于字符串 "www.hyzhou.com.cn" 输出 "cn.com.hyzhou.www"         代码简单明了,就不写注释了,是在看不懂,自己调试

御坂的专栏 1337

利用计算机属性将字符串逆序输出,字符串逆序的各种实现算法

很早就准备写一个字符串系列的面试题,本来已经写好了,大概有十几道题,但是写完才发现,文章好长,连我自己都没有耐心读下去了,索性就将其拆分成几个系列,一来分开后篇幅变小,看起来比较方便。二来也更有针对性,便于精雕细作。比如这篇,在原来的文章中只占很小的篇幅,但是独立出来才发现,东西也不少。既然是第一篇,就来个最最简单的字符串逆序吧。字符串逆序可以说是最经常考的题目。这是一道入门级的题目,相信80%的...

weixin_42297390的博客 526

字符串反转的9种方法

1. 使用Array.Reverse方法 对于字符串反转,我们可以使用.NET类库自带的Array.Reverse方法 public static string ReverseByArray(string original) { char[] c = original.ToCharArray(); Array.Reverse(c); return new string(c); }

迷之月光的专栏 1万+

编程珠玑 Chapter2 字符串翻转算法

没办法,久没练过算法,只好用Java写了。 题目很简单: Q: abcdefg, r=3 A: defgabc 代码一:借助StringBuffer的append来做。即一部分一部分来求逆,然后再“拼接”起来求逆。 public class Rotate { /** * Rotate a String by reversing it partly and then

陌上 1212
上一篇: Flex数据类型
下一篇: java责任链模式
hatom
博客等级 码龄15年 46粉丝 39原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值