数据结构04附录01:字符串大写转小写[C++]

 

图源:文心一言

上机题目练习整理~🥝🥝

本篇作为字符串的代码补充,提供了3种(差别并不大)解法以及函数的详细解释,供小伙伴们参考~🥝🥝

前文:🌸数据结构04:串的存储结构与KMP算法_串的三种存储方式-CSDN博客

  • 第1版:在力扣新手村刷题的记录,方法一与方法二是 文心一言 老师提供的建议,方法三是力扣的官方解法~🧩🧩

编辑:梅头脑🌸

题目:709. 转换成小写字母 - 力扣(LeetCode)


📇目录

🧵转换小写字母的题目

🧩题目

🌰方法一:for循环 + 转小写函数tolower

🌰方法二:transform转换 + 转小写函数tolower

🌰方法三:for循环 + ASCII码

🔚结语


🧵转换小写字母的题目

🧩题目

给你一个字符串 s ,将该字符串中的大写字母转换成相同的小写字母,返回新的字符串。

示例 1:

输入:s = "Hello"
输出:"hello"

示例 2:

输入:s = "here"
输出:"here"

示例 3:

输入:s = "LOVELY"
输出:"lovely"

🌰方法一:for循环 + 转小写函数tolower

📇算法思路

  • 算法思想:使用for循环,对于字符串中的每个字母转小写~
  • 时间复杂度:O(n),其中n是数组的长度,该代码对字符串中的每个字符都进行了操作。
  • 空间复杂度:O(1),其中n是数组的长度,该代码直接在原字符串上进行操作,没有使用额外的存储空间。

 ⌨️算法代码

class Solution {
public:
    string toLowerCase(string s) {    // 返回类型为string的方法,名为toLowerCase。它接受一个名为s的字符串参数
        for (char &c : s) {           // 基于范围的for循环,用于遍历字符串s中的每一个字符。这里使用的是C++11中的范围for循环语法
           c = std::tolower(c);       // 对于字符串s中的每个字符c,都调用了std::tolower函数。这个函数是C++标准库中的一个函数,用于将大写字母转换为小写字母
        }
        return s;  // 返回转换后的字符串  // 返回原始字符串s
    }
};

 ⌨️温馨提示

可能问题:请注意,以下写法可能会导致下图的执行错误:

  • 第4行直接写为:“for (char c : s)”,而非for (char &c : s)
  • 第5行直接写为:“std::tolower(c);”,而非c = std::tolower(c);

问题所在:由于std::tolower(c);没有将结果存储回原字符c,所以实际上有些字符未被转换为小写。因此,当我们尝试返回原始字符串时,它仍然是原来的大小写形式。

        

⌨️函数解释

基于范围的for循环(Range-based for loop) 

是C++11中引入的一种新特性,它允许我们更简洁、更直观地遍历容器(如数组、字符串、向量等)中的元素。

这种循环的基本语法如下:

for (element_type value : container) {  
    // 循环体  
}
  • element_type 是容器中元素的类型,
  • value 是我们为每个元素定义的临时变量名,
  • container 是要遍历的容器。

 为什么使用基于范围的for循环?

  1. 简洁性:它避免了使用传统的迭代器,使代码更简洁。
  2. 直观性:对于不熟悉迭代器的开发者来说,基于范围的for循环更直观,更容易理解。
  3. 性能:在某些情况下,基于范围的for循环可能比使用迭代器更快,因为编译器可以进行更多的优化。

例子

假设我们有一个整数数组,并想打印出数组中的所有元素:

使用传统的迭代器:

#include <iostream>

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    for (int *it = arr; it != arr + 5; ++it) {
        std::cout << *it << ' ';
    }

    return 0;
}

 使用基于范围的for循环:

#include <iostream>

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    for (int value : arr) {
        std::cout << value << ' ';
    }

    return 0;
}

 基于范围的for循环不仅适用于数组,还适用于所有支持迭代器的容器,如std::vectorstd::stringstd::list等。

例如本题就是基于std::string的遍历~~

🌰方法二:transform转换 + 转小写函数tolower

📇算法思路

  • 算法思想:将循环替换为transform,也可以达到对字符串中的字符逐个操作的结果;
  • 时间复杂度:O(n),其中n是数组的长度,该代码对字符串中的每个字符都进行了操作。
  • 空间复杂度:O(1),其中n是数组的长度,该代码直接在原字符串上进行操作,没有使用额外的存储空间。

 ⌨️算法代码

class Solution {
public:
    string toLowerCase(string s) { 
        std::transform(s.begin(), s.end(), s.begin(), ::tolower);  // 将所有字符转换为小写  
        return s;  // 返回转换后的字符串  
    }
};
⌨️函数解释
  1. std::transform: 这是C++标准库中的函数,用于对容器中的元素进行转换。
  2. s.begin(), s.end(): 这两个参数定义了一个范围,即从字符串s的开始到结束。这意味着我们要对字符串s中的所有字符进行操作。
  3. s.begin(): 这是输出迭代器,表示转换后的字符应该被写入的位置。因为我们要将转换后的字符覆盖原字符串,所以输出迭代器就是s.begin()
  4. ::tolower: 这是一个函数指针,指向C标准库中的tolower函数。这个函数的作用是将大写字母转换为小写字母。

⌨️知识扩展

transform

参考原文:C++ transform(STL transform)函数用法详解 (biancheng.net)

transform() 可以将函数应用到序列的元素上,并将这个函数返回的值保存到另一个序列中,它返回的迭代器指向输出序列所保存的最后一个元素的下一个位置。

  • 这个序列可以是字符串,如本题;
  • 这个序列可以是向量容器,例如以下举栗在向量中存储的数据 从 摄氏度转换到 华氏度。
    • std::vector<double> deg_C {21.0, 30.5, 0.0, 3.2, 100.0};
      std::vector<double> deg_F(deg_C.size());
      std::transform(std::begin(deg_C), std::end(deg_C), std::begin(deg_F),[](double temp){ return 32.0 + 9.0*temp/5.0; });
      //Result 69.8 86.9 32 37.76 212
    • 第1行代码创建了一个名为 deg_C 的向量,并初始化了五个浮点数;
    • 第2行代码创建了一个新的向量 deg_F,其大小与 deg_C 相同。这个新向量被初始化为空。
    • 第3行使用了 std::transform 算法来转换 deg_C 中的数据,并将结果存储在 deg_F 中。
      • std::begin(deg_C) 和 std::end(deg_C):这两个函数是定义输入序列的输入迭代器,指向 deg_C 向量的开始和结束。
      • std::begin(deg_F):是目的位置的第一个元素的输出迭代器,指向 deg_F 向量的开始。(值得注意的是,如果是rbegin,则为反向迭代器,指向容器中的最后一个元素)
      • [](double temp){ return 32.0 + 9.0*temp/5.0; }:这是一个 lambda 函数,用于将摄氏度转换为华氏度。转换公式是:F = C × 9/5 + 32。

上述代码感兴趣可以直接运行这个:

#include <iostream>
#include <vector>
#include <algorithm>  // 为了使用 std::transform

int main() {
    std::vector<double> deg_C {21.0, 30.5, 0.0, 3.2, 100.0};
    std::vector<double> deg_F(deg_C.size());

    std::transform(std::begin(deg_C), std::end(deg_C), std::begin(deg_F), [](double temp) { return 32.0 + 9.0 * temp / 5.0; });

    // 打印转换结果
    for (const auto& temp : deg_F) {
        std::cout << temp << " ";
    }

    return 0;
}

用静态数组也可以,不过文心老师温馨提醒,实际使用过程中,数组长度一般是固定的,灵活性小于容器,且不负责内存管理~

#include <iostream>

int main() {
    double deg_C[] = {21.0, 30.5, 0.0, 3.2, 100.0};
    double deg_F[5];  // 注意大小固定为5

    for (size_t i = 0; i < 5; ++i) {
        deg_F[i] = 32.0 + 9.0 * deg_C[i] / 5.0;
    }

    // 打印转换结果
    for (size_t i = 0; i < 5; ++i) {
        std::cout << deg_F[i] << " ";
    }

    return 0;
}

🌰方法三:for循环 + ASCII码

📇算法思路

  • 算法思想:
    • ASCII码中,小写字母a-z的码值为97-122。因此,要将大写字母A-Z转换为小写字母,只需将对应的大写字母码值加上32即可;
    • 例如,大写字母A的码值为65,转换为小写字母a的码值为97(65+32);

图源:java数据类型转换_java里面long转换对应的ascii码-CSDN博客

⌨️算法代码

class Solution {
public:
    string toLowerCase(string s) {
        for (char& ch: s) {
            if (ch >= 65 && ch <= 90) {    // 如果字符为大写,即ASCII码介于65-90
                ch |= 32;                  // 对 ch 的 ASCII码与 32 做按位或运算,替代与 32的加法运算。
            }
        }
        return s;
    }
};

作者:力扣官方题解
来源:https://leetcode.cn/problems/to-lower-case/solutions/1151839/zhuan-huan-cheng-xiao-xie-zi-mu-by-leetc-5e29/

⌨️算法解释

第6行完全可以使用 ch = ch + 32;而官方采用了按位或运算ch |= 32,这么修改的条件如下:

  • 正好[65,90] 对应的二进制表示为 [(01000001)2,(01011010)2],观察从高到低第3位恒为0;
  • 32对应的二进制为(00100000)2,观察从高到低第3位恒为1;
  • 0和1相与为1,刚好就是相加的结果,对于这道题,可以用按位或代替相加的功能;
  • 不晓得是不是业内主流做法,因为按位与比相加快很多;相反,如果不能保证被加数与加数的相应位数刚好错开,就不能这么玩了。

🔚结语

博文到此结束,写得模糊或者有误之处,欢迎小伙伴留言讨论与批评,督促博主优化内容{例如有错误、难理解、不简洁、缺功能}等,博主会顶锅前来修改~~😶‍🌫️😶‍🌫️

我是梅头脑,本片博文若有帮助,欢迎小伙伴动动可爱的小手默默给个赞支持一下,感谢点赞小伙伴对于博主的支持~~🌟🌟

同系列的博文在以下链接~~🌸🌸

数据结构_梅头脑_的博客-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/weixin_42789937/category_12262100.html?spm=1001.2014.3001.5482

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

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

相关文章

最全的软件测试面试题(含答案)

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;软件测试面试题分享&#xff1a; 1000道软件测试面试题及答案&#x1f4e2;软件测试实战项目分享&#xff1a; 纯接口项目-完…

ME6211C33M5G-N 输出3.3V 500mA 线性稳压器LDO 参数

描述 ME6211系列是高精度&#xff0c;低噪声&#xff0c;CMOS LDO电压调压器。ME6211系列提供低输出噪声&#xff0c;高纹波抑制率&#xff0c;低辍学率和非常快速的开启时间&#xff0c;ME6211系列是当今最前沿的手机的理想选择。ME6211内部包括参考电压源、误差放大器、驱动…

Python从入门到精通 第十一章(面向对象)

一、类和对象 1、面向对象基本概念 &#xff08;1&#xff09;之前学习的编程方式是面向过程的&#xff0c;面向过程和面向对象是两种不同的编程方式。 &#xff08;2&#xff09;过程和函数&#xff1a;过程是早期的一个编程概念&#xff0c;过程类似于函数&#xff0c;只能…

DDNS-GO配置使用教程

环境&#xff1a;openwrt 下载地址&#xff1a;Releases jeessy2/ddns-go GitHub 下载 ssh至openwrt根目录&#xff0c;根据你的处理器选择要下载的版本&#xff0c;我是路由器&#xff0c;选择的是 ddns-go_5.7.1_linux_arm64.tar.gz wget github链接 安装 tar -zxvf…

对象图作业

对象图作业 一. 简答题&#xff08;共3题&#xff0c;100分&#xff09; (简答题) 对象特性的三要素是什么&#xff0c;请通过一个实际的例子来说明三要素的内容。 正确答案&#xff1a; 对象特性的三要素是状态、行为和标识。 张三对象具有身高、体重、学历、职务、收入等状态…

Flink 2.0 状态管理存算分离架构演进

Flink 2.0 状态管理存算分离架构演进 flink 现有状态访问线程模型首先简单来说一下,flink2.0做存算分离,最最主要的一点是解决,大状态的问题,例如一个超过50T的物流数据,大状态恢复可能就要1天,所以才有存算分离这么一个设计初衷。 下面先来看一下 任务是怎么执行提交的,…

浅研究下 DHCP 和 chrony

服务程序&#xff1a; 1.如果有默认配置&#xff0c;请先备份&#xff0c;再进行修改 2.修改完配置文件&#xff0c;请重启服务或重新加载配置文件&#xff0c;否则不生效 有些软件&#xff0c;安装包的名字和系统里服务程序的名字不一样&#xff08;安装包名字&#xff1a;…

Springboot+vue学生考试系统

Springbootvue学生考试系统 演示视频 【Springbootvue学生考试系统】 https://www.bilibili.com/video/BV1gk4y1Q7em/?share_sourcecopy_web&vd_source11344bb73ef9b33550b8202d07ae139b 主要功能&#xff1a; 管理员可以添加题库分配课程教师&#xff0c;指定考试范围指定…

【教3妹学编程-算法题】统计出现过一次的公共字符串

3妹&#xff1a;哈哈哈哈哈哈&#xff0c;太搞笑了~ 呵呵呵呵呵呵 2哥&#xff1a;3妹干嘛呢&#xff0c; 笑的这么魔性&#xff01; 3妹&#xff1a;在看王牌对王牌&#xff0c;老搞笑了 2哥&#xff1a;这季好像没有贾玲吧。 3妹&#xff1a;是啊&#xff0c;听说贾玲去导电影…

仿真验证方法(2)——静态验证

一、静态验证 1.1 概述 在之前的文章中&#xff0c;我们介绍了动态仿真&#xff0c;但是动态仿真用于百万门以上电路时所需时间极长&#xff0c;而且其功能覆盖率取决于所设计的输入激励向量&#xff0c;很难达到100%&#xff0c;因此静态时序分析和等效性检查这样的静态验证是…

MySQL篇—自带物理克隆数据工具Clone插件介绍(第一篇,总共三篇)

各位小伙伴&#xff0c;今天我为大家介绍一下MySQL Clone Plugin这个插件&#xff0c;简单来说&#xff0c;就是MySQL 8.0.17版本之后的一个物理克隆数据工具&#xff0c;它能够帮助我们快速、高效地克隆或复制数据库&#xff0c;极大地简化了数据库迁移、备份和恢复的过程&…

老老实实的程序员该如何描述自己的缺点

答辩的时候&#xff0c;晋升的时候&#xff0c;面试的时候&#xff0c;你有没有经常遇到一个问题&#xff0c;那就是你觉得自己有什么缺点吗&#xff1f; 目录 1. 每个人都有缺点 2. 这道题在考什么&#xff1f; 3. 我之前是怎么回答的 4. 你可以这样回答试一试 5. 总结 …

transbigdata笔记:数据栅格化

1 area_to_grid 在边界或形状中生成矩形栅格 1.1 主要使用方法 transbigdata.area_to_grid(location, accuracy500, methodrect, paramsauto) 1.2 主要参数 location (bounds(List) or shape(GeoDataFrame) 生成栅格的位置。 如果边界为 [lon1&#xff0c; lat1&#xff0…

JS中垃圾数据是如何自动回收的

JS中垃圾数据是如何自动回收的 背景垃圾回收机制调用栈中的数据回收堆空间中数据回收垃圾回收器的工作流程副垃圾回收器主垃圾回收器 全停顿 背景 在JS栈和堆&#xff1a;数据是如何存储的一文中提到了 JavaScript 中的数据是如何存储的&#xff0c;并通过示例代码分析了原始数…

MySQL深入——9

如何正确的显示随机信息&#xff1f; 我们来模拟在英语单词app当中随机出现三个英语单词的情况&#xff0c;我们首先创建一张表words&#xff0c;然后给这个表当中插入10000条信息进行量化。 select word from words order by rand() limit 3&#xff1b; order by rand&…

Python - 操作 docx

文章目录 使用库 : python-docx 官方文档&#xff1a;https://python-docx.readthedocs.io 安装 pip install python-docx提取 docx from docx import Documentdoc Document(file_path) text "" for para in doc.paragraphs:text para.text "\n"创建…

gazebo模型库目录(国内源)

这个是比较普遍的&#xff0c;一般用途&#xff1a; GitCode - 开发者的代码家园https://gitcode.com/geniusChinaHN/osrf.gazebo_models/tree/master/ambulance这个主要是车辆&#xff1a; car_demo: osrf汽车模型库https://gitee.com/geniuschinahn/car_demo还有这个是以前…

深入理解 Flink(八)Flink Task 部署初始化和启动详解

JobMaster 部署 Task 核心入口&#xff1a; JobMaster.onStart();部署 Task 链条&#xff1a;JobMaster --> DefaultScheduler --> SchedulingStrategy --> ExecutionVertex --> Execution --> RPC请求 --> TaskExecutor TaskExecutor 处理 JobMaster 的 …

一文玩转Go语言中的面向对象编程~

温故而知新&#xff1a;什么是面向对象 面向对象&#xff08;Object-Oriented&#xff09;是一种计算机编程的方法和思想&#xff0c;它将程序中的数据&#xff08;对象&#xff09;和操作&#xff08;方法&#xff09;组织成一个个相互关联和交互的对象。对象是现实世界中的事…

SpringBoot 配置文件加载优先级

SpringBoot 配置文件加载优先级 前言SpringBoot 配置文件加载优先级 前言 最近在使用k8s部署项目的时候,发现Dockerfile文件中的命令后面跟的参数,无法覆盖nacos中的参数,今天有时间正好来整理一下Springboot配置的加载顺序 SpringBoot 配置文件加载优先级 整理加载顺序第一个肯…