【C语言】字符串左旋的三种解题方法详细分析


在这里插入图片描述

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳]
本文专栏: C语言

文章目录

  • 💯前言
  • 💯题目描述
  • 💯方法一:逐字符移动法
  • 💯方法二:使用辅助空间法
  • 💯方法三:三次反转法
  • 💯方法对比与总结
    • 拓展思考
  • 💯总结

在这里插入图片描述


在这里插入图片描述


💯前言

  • 在这篇文章中,我们将深入探讨字符串左旋的三种解决方案,系统分析每种方法的算法设计时间复杂度空间复杂度,以及其适用场景局限性。这些方法从简单到高效,分别展示了逐字符移动法使用辅助空间法三次反转法的不同特点及其理论基础
    通过对这些方法的详细对比讨论,读者将对字符串操作基本原理有更为深入的理解,掌握在不同应用场景下如何选择最优的解决方案,以提升代码的效率鲁棒性
    C语言
    在这里插入图片描述

💯题目描述

实现一个函数,能够左旋字符串中的 k 个字符。

例如:

  • 给定字符串 ABCD,如果左旋 1 个字符,得到 BCDA
  • 如果左旋 2 个字符,得到 CDAB

左旋是指将字符串的前面部分字符移到字符串的末尾。我们将使用三种不同的实现方式来解决这一问题:逐字符移动法、使用辅助空间法、以及三次反转法。


💯方法一:逐字符移动法

思路

逐字符移动法是一种直观的实现方式,通过多次迭代将字符串的第一个字符移动到末尾,直到完成所需的旋转次数。该方法依赖于不断移动字符的位置以达到最终目标。其本质是一种线性搬移操作,容易理解,但在大数据量的情况下效率较低。
在这里插入图片描述

代码实现

void leftRound(char* str, int k) {
    int len = strlen(str);
    int time = k % len;

    for (int i = 0; i < time; i++) {
        char tmp = str[0];
        int j = 0;
        for (; j < len - 1; j++) {
            str[j] = str[j + 1];
        }
        str[j] = tmp;
    }
}

int main() {
    char str[] = "abcdef";
    leftRound(str, 7);
    printf("%s\n", str);
    return 0;
}

解释

  • 获取字符串长度 len
  • 计算实际旋转次数 time = k % len,这样可以避免 k 超过字符串长度导致的冗余操作。
  • 外层循环用于执行 time 次旋转,每次只移动一个字符。
  • 使用内部的 for 循环,将每个字符依次前移一个位置,最后将原来的第一个字符移到末尾。

时间复杂度和空间复杂度

  • 时间复杂度:O(k * len),对于每次旋转都需要遍历整个字符串,因而效率较低。
  • 空间复杂度:O(1),只需一个额外的字符变量来暂存被移动的字符。

优缺点

  • 这种方法的优点是实现简单且易于理解,适合初学者用于理解字符串旋转的基本概念。但其缺点在于效率较低,尤其在 k 较大和字符串长度较长时,由于需要多次逐字符移动,时间开销会显著增加。

💯方法二:使用辅助空间法

思路

使用辅助空间法通过将旋转后的字符串临时保存,再将结果复制回原字符串。借助辅助空间将两个部分拼接,可以有效避免逐字符移动带来的低效问题。该方法的核心在于利用辅助数组,快速完成字符串的局部重组与合并
在这里插入图片描述

代码实现

void leftRound(char* str, int k) {
    int len = strlen(str);
    int time = k % len;
    char tmp[256] = { 0 };

    strcpy(tmp, str + time); 
    strncat(tmp, str, time); 
    strcpy(str, tmp);
}

int main() {
    char str[] = "abcdef";
    leftRound(str, 7);
    printf("%s\n", str);
    return 0;
}

解释

  • 通过 strlen 获取字符串的长度。
  • 计算实际的旋转次数 time = k % len,以应对 k 过大时的情况。
  • 使用临时数组 tmp 存储旋转后的结果。
  • 利用 strcpy 函数将原字符串从 time 索引位置开始的部分复制到 tmp 中。
    • strcpy(tmp, str + time)str + time 表示指向原字符串从第 time 个位置开始的指针,strcpy 函数将从这个位置开始的所有字符(直到字符串结束符 )复制到 tmp 中。因此,tmp 中最初会存储字符串的后半部分。例如,若 str = "ABCD"time = 2strcpy(tmp, str + time)"CD" 复制到 tmp,结果为 tmp = "CD"
  • 使用 strncat 函数将原字符串的前 time 个字符拼接到 tmp 的末尾。
    • strncat(tmp, str, time)strncat 用于将源字符串的指定数量字符拼接到目标字符串的末尾。在这里,str 表示原字符串,time 表示从 str 开头开始的 time 个字符。因此,strncat(tmp, str, time) 将原字符串的前 time 个字符(即 "AB")拼接到 tmp 的末尾,形成最终结果。例如,当 tmp = "CD"time = 2 时,拼接后结果为 tmp = "CDAB"
  • 最后使用 strcpytmp 的内容复制回原字符串 str,完成旋转操作。

时间复杂度和空间复杂度

  • 时间复杂度:O(n),只需遍历字符串几次即可完成旋转。
  • 空间复杂度:O(n),需要额外的存储空间来保存旋转后的结果。

优缺点

  • 辅助空间法的优势在于其高效的操作,尤其适合处理较大的字符串,但需要额外的空间来存储结果。因此,对于内存资源受限的情况,该方法可能不太适合。

💯方法三:三次反转法

思路

三次反转法通过对字符串的部分片段进行反转,从而达到整体左旋的效果。核心思想是将字符串划分为两部分,分别反转,再对整体反转,以实现最终的左旋

这种方法以极少的操作步骤完成字符位置的重新排列,具有较高的效率数学美感

在这里插入图片描述

代码实现

void ReverseRange(char* str, int start, int end) {
    int left = start;
    int right = end;
    while (left < right) {
        char tmp = str[left];
        str[left] = str[right];
        str[right] = tmp;
        left++;
        right--;
    }
}

void leftRound(char* str, int k) {
    int len = strlen(str);
    int time = k % len;
    ReverseRange(str, 0, time - 1);    // 反转前 time 个字符
    ReverseRange(str, time, len - 1);  // 反转剩余部分
    ReverseRange(str, 0, len - 1);     // 反转整个字符串
}

int main() {
    char str[] = "abcdef";
    leftRound(str, 7);
    printf("%s\n", str);
    return 0;
}

解释

  1. 反转前 time 个字符

    • 调用 ReverseRange(str, 0, time - 1),反转字符串的前 time 个字符。
    • 例如,对 "ABCD" 反转前两个字符,得到 "BACD"
  2. 反转剩余部分

    • 调用 ReverseRange(str, time, len - 1),反转剩余部分。
    • "BACD" 中的后两个字符反转,得到 "BADC"
  3. 反转整个字符串

    • 调用 ReverseRange(str, 0, len - 1),反转整个字符串。
    • "BADC" 反转得到 "CDAB",从而完成左旋操作。

时间复杂度和空间复杂度

  • 时间复杂度:O(n),三次反转操作均为线性时间复杂度,因此总时间复杂度为 O(n)
  • 空间复杂度:O(1),只需进行交换操作,没有额外的空间开销。

优缺点

  • 三次反转法的优势在于其高效性,时间复杂度为 O(n),空间复杂度为 O(1),适合处理大规模字符串。该方法通过反转实现字符串的重新排列,以最小的时间和空间成本实现左旋,非常适合实际开发中的高效实现。

💯方法对比与总结

方法时间复杂度空间复杂度优点缺点
逐字符移动法O(k * n)O(1)实现简单,直观效率较低
辅助空间法O(n)O(n)实现高效,代码简洁需要额外空间
三次反转法O(n)O(1)高效且无额外空间开销实现稍复杂,需要三次反转
  • 逐字符移动法 适合初学者理解字符串旋转的概念,但效率不高。在字符较多或者旋转次数较大时,可能会因为需要逐次移动而显得低效
  • 辅助空间法 则通过一次性拼接字符串提升了效率,但需要额外的空间存储,对于空间资源紧张的场景可能不适合
  • 三次反转法最优的方法,尤其适合大规模字符串。它的空间复杂度最低效率高,是一个非常经典的字符串操作技巧。该方法不仅巧妙而且具有一定的数学美感,通过三次反转将字符串重新排列到目标位置。

拓展思考

  • 这些字符串旋转的实现方法可以拓展到其他类型的数据结构,例如数组的左旋、右旋操作。对于数组来说,三次反转法同样有效,可以通过类似的思路对数组元素进行重新排列。
  • 三次反转法的思想不仅可以用于字符串旋转,还可以用于链表数组等其他序列的数据结构。它是一种通用的思想,可以帮助解决许多涉及顺序调整的问题。
  • 对于多种编程语言,我们也可以找到相似的实现方法。Python 中可以使用字符串切片操作来轻松实现左旋,而 Java 中可以借助 StringBuilder 进行高效的字符串操作。Python 的切片方法非常直观,例如可以使用 s = s[k:] + s[:k] 来实现左旋操作,简洁而高效。
  • 对于面试场景,理解这些方法的时间复杂度空间复杂度,以及不同方法在实际应用中的适用性非常重要。面试官通常希望看到你对基础方法的掌握以及对最优解法的深入理解。

💯总结

  • 在这里插入图片描述
    字符串左旋是一个非常基础但又非常经典的字符串操作问题。通过这篇文章的深入解读,我们详细探讨了三种不同的解决方案,并对每种方法的算法复杂度适用场景优缺点进行了深入分析。掌握这些方法有助于我们在面试中应对字符串操作类的问题,也能帮助我们在实际开发中写出更优雅、高效的代码。这三种方法展示了从基础到高效的不同解决思路,是学习和掌握字符串操作的宝贵经验
    希望这篇文章能够激发你对字符串操作的更深入思考与理解。未来的学习和工作中,愿你能够灵活应用这些技巧,优化代码的效率与可读性,深入理解不同方法背后的原理,并能够在解决问题时选择最合适的工具。这正是编程的艺术,也是不断提升的动力所在

在这里插入图片描述


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

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

相关文章

【AI绘画】Midjourney进阶:色调详解(上)

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: AI绘画 | Midjourney 文章目录 &#x1f4af;前言&#x1f4af;Midjourney中的色彩控制为什么要控制色彩&#xff1f;为什么要在Midjourney中控制色彩&#xff1f; &#x1f4af;色调白色调淡色调明色调 &#x1f4af…

零基础学安全--云技术基础

目录 学习连接 前言 云技术历史 云服务 公有云服务商 云分类 基础设施即服务&#xff08;IaaS&#xff09; 平台即服务&#xff08;PaaS&#xff09; 软件即服务&#xff08;SaaS&#xff09; 云架构 虚拟化 容器 云架构设计 组件选择 基础设施即代码 集成部署…

【Linux】网络通信

TCP协议是一个安全的、面向连接的、流式传输协议&#xff0c;所谓的面向连接就是三次握手&#xff0c;对于程序猿来说只需要在客户端调用connect()函数&#xff0c;三次握手就自动进行了。先通过下图看一下TCP协议的格式&#xff0c;然后再介绍三次握手的具体流程。 TCP的三次握…

Pgsql:json字段查询与更新

1.查询json字段的值 SELECT attribute_data->>设施类别 mycol, * FROM gis_coord_data WHERE attribute_data->>设施类别阀门井 查询结果如下&#xff1a; 2.更新json字段中的某个属性值 UPDATE gis_coord_data SET attribute_data(attribute_data::jsonb ||{&quo…

对于GC方面,在使用Elasticsearch时要注意什么?

大家好&#xff0c;我是锋哥。今天分享关于【对于GC方面&#xff0c;在使用Elasticsearch时要注意什么&#xff1f;】面试题。希望对大家有帮助&#xff1b; 对于GC方面&#xff0c;在使用Elasticsearch时要注意什么&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java…

基于Netty实现聊天室

前言 了解了Netty的基本功能和相关概念&#xff0c;使用基于Netty实现多人聊天的功能。 需求 1.服务端能够接收客户端的注册&#xff0c;并且接受用户的信息注册 2.服务端能够处理客户端发送的消息&#xff0c;并且根据消息类型进行私发或者广播发送消 3.服务端能够私发消…

Linux -日志 | 线程池 | 线程安全 | 死锁

文章目录 1.日志1.1日志介绍1.2策略模式1.3实现日志类 2.线程池2.1线程池介绍2.2线程池的应用场景2.3线程池的设计2.4代码实现2.5修改为单例模式 3.线程安全和函数重入问题3.1线程安全和函数重入的概念3.2总结 4.死锁4.1什么是死锁4.2产生死锁的必要条件4.3避免死锁 1.日志 1.…

【博主推荐】C#的winfrom应用中datagridview常见问题及解决方案汇总

文章目录 1.datagridview绘制出现鼠标悬浮数据变空白2.datagridview在每列前动态添加序号2.1 加载数据集完成后绘制序号2.2 RowPostPaint事件绘制 3.datagridview改变行样式4.datagridview后台修改指定列数据5.datagridview固定某个列宽6.datagridview某个列的显示隐藏7.datagr…

【设计模式】创建型模式之单例模式(饿汉式 懒汉式 Golang实现)

定义 一个类只允许创建一个对象或实例&#xff0c;而且自行实例化并向整个系统提供该实例&#xff0c;这个类就是一个单例类&#xff0c;它提供全局访问的方法。这种设计模式叫单例设计模式&#xff0c;简称单例模式。 单例模式的要点&#xff1a; 某个类只能有一个实例必须…

Vivado程序固化到Flash

在上板调试FPGA时&#xff0c;通常使用JTAG接口下载程序到FPGA芯片中&#xff0c;FPGA本身是基于RAM工艺的器件&#xff0c;因此掉电后会丢失芯片内的程序&#xff0c;需要重新烧写程序。但是当程序需要投入使用时不能每一次都使用JTAG接口下载程序&#xff0c;一般FPGA的外围会…

技术文档,they are my collection!

工作 今天这篇文章&#xff0c;献给一直撰写技术文档的自己。我自认为是公司中最爱写文档的人了&#xff0c;我们是一个不到40人的小公司&#xff0c;公司作风没有多么严谨&#xff0c;领导也不会要求我们写技术文档。但是从入职初至今&#xff0c;我一直保持着写技术文档…

微信小程序学习指南从入门到精通

&#x1f5fd;微信小程序学习指南从入门到精通&#x1f5fd; &#x1f51d;微信小程序学习指南从入门到精通&#x1f51d;✍前言✍&#x1f4bb;微信小程序学习指南前言&#x1f4bb;一、&#x1f680;文章列表&#x1f680;二、&#x1f52f;教程文章的好处&#x1f52f;1. ✅…

JavaWeb——SpringBoot原理

10.1. 配置优先级 10.1.1. 配置文件 properties > yml(推荐) > yaml 10.1.2. Java系统属性、命令行参数 命令行参数 > Java系统属性 > 配置文件 10.2. Bean管理 10.2.1. 手动获取bean ApplicationContext&#xff0c;IOC容器对象 10.2.2. bean作用域 10.2.3.…

如何在Python中进行数学建模?

数学建模是数据科学中使用的强大工具&#xff0c;通过数学方程和算法来表示真实世界的系统和现象。Python拥有丰富的库生态系统&#xff0c;为开发和实现数学模型提供了一个很好的平台。本文将指导您完成Python中的数学建模过程&#xff0c;重点关注数据科学中的应用。 数学建…

OCR技术详解:从基础到应用

OCR技术详解&#xff1a;从基础到应用 引言 OCR技术的定义 OCR&#xff08;Optical Character Recognition&#xff0c;光学字符识别&#xff09;是一种将印刷或手写文本转换为机器可读文本的技术。通过OCR技术&#xff0c;计算机可以自动识别图像中的文字&#xff0c;并将其…

webrtc视频会议学习(三)

文章目录 关联&#xff1a;源码搭建coturn服务器nginx配置ice配置需服务器要开放的端口 效果 关联&#xff1a; webrtcP2P音视频通话&#xff08;一&#xff09; webrtcP2P音视频通话&#xff08;二&#xff09; webrtc视频会议学习&#xff08;三&#xff09; 源码 WebRTC…

【从零开始的LeetCode-算法】43. 网络延迟时间

有 n 个网络节点&#xff0c;标记为 1 到 n。 给你一个列表 times&#xff0c;表示信号经过 有向 边的传递时间。 times[i] (ui, vi, wi)&#xff0c;其中 ui 是源节点&#xff0c;vi 是目标节点&#xff0c; wi 是一个信号从源节点传递到目标节点的时间。 现在&#xff0c;…

数据结构--AVL树(平衡二叉树)

✅博客主页:爆打维c-CSDN博客​​​​​​ &#x1f43e; &#x1f539;分享c、c知识及代码 &#x1f43e; &#x1f539;Gitee代码仓库 五彩斑斓黑1 (colorful-black-1) - Gitee.com 一、AVL树是什么&#xff1f;&#xff08;含义、性质&#xff09; 1.AVL树的概念 AVL树是最…

sunshine和moonlight串流网络丢失帧高的问题(局域网)

注&#xff1a;此贴结果仅供参考 场景环境&#xff1a;单身公寓 路由器&#xff1a;2016年的路由器 开始&#xff1a;电脑安装sunshine软件&#xff0c;手机安装moonlight软件开始串流发现网络丢失帧发现巨高 一开始怀疑就是路由器问题&#xff0c;因为是局域网&#xff0c;而…

STM32F103外部中断配置

一、外部中断 在上一节我们介绍了STM32f103的嵌套向量中断控制器&#xff0c;其中包括中断的使能、失能、中断优先级分组以及中断优先级配置等内容。 1.1 外部中断/事件控制器 在STM32f103支持的60个可屏蔽中断中&#xff0c;有一些比较特殊的中断&#xff1a; 中断编号13 EXTI…