当前位置: 首页 > news >正文

letcode - string

翻转字符串

344. 反转字符串 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/reverse-string/

class Solution {
public:void reverseString(vector<char>& s) {reverse(s.begin(),s.end());//直接上逆置接口}
};
  1. 函数签名:

  2. void reverseString(vector<char>& s);

    这个函数不返回任何值 (void),并且接受一个 vector<char> 类型的引用 s 作为输入参数。

  3. 调用 std::reverse 函数:

    reverse(s.begin(), s.end());

    使用标准库中的 std::reverse 函数来反转 vector<char> 中的元素。s.begin() 返回指向向量第一个元素的迭代器,s.end() 返回指向向量最后一个元素之后的一个位置的迭代器。因此,std::reverse 会将 s 中的所有元素进行反转。


翻转字符串||

541. 反转字符串 II - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/reverse-string-ii/description/

问题描述

给定一个字符串 s 和一个整数 k,任务是反转每 2k 个字符中的前 k 个字符。如果剩余字符不足 k 个,则将这些字符全部反转。

示例

  • 输入: s = "abcdefghi", k = 3
  • 输出: "cbadefghi"

解释

  1. 字符串按长度 2k 划分为几个部分。
  2. 对于每个部分,前 k 个字符被反转。
  3. 部分中剩余的字符(如果有)保持不变。
  4. 将所有部分串联起来形成结果。

代码解释

class Solution {
public:string reverseStr(string s, int k) {int pos = 0; // 开始反转或向前移动的位置// 循环遍历整个字符串直到结束while (pos < s.size()) {// 如果还剩下至少 k 个字符,反转前 k 个字符if (pos + k < s.size()) {reverse(s.begin() + pos, s.begin() + pos + k);} else {// 否则,反转所有剩余字符reverse(s.begin() + pos, s.end());}// 将位置向前移动 2k 以进入下一个块pos += 2 * k;}return s;}
};
  1. 函数签名:

    string reverseStr(string s, int k);

    这个函数返回一个字符串,并接受一个字符串 s 和一个整数 k 作为输入参数。

  2. 变量初始化:

    int pos = 0; // 开始反转或向前移动的位置

    pos 是一个整型变量,用来记录当前处理到字符串中的哪个位置。初始时 pos 被设置为 0,即从字符串的起始位置开始处理。

  3. 循环处理字符串:

    while (pos < s.size()) {// ...
    }

    使用 while 循环遍历整个字符串,直到 pos 超过字符串的长度。

  4. 条件判断与反转操作:

    if (pos + k < s.size()) {reverse(s.begin() + pos, s.begin() + pos + k);
    } else {reverse(s.begin() + pos, s.end());
    }
    • 如果当前位置加上 k 仍然小于字符串的长度,那么就反转从 pos 到 pos + k 之间的字符。
    • 否则,如果剩余的字符不足 k 个,就反转从 pos 到字符串结尾的所有字符。
  5. 更新位置:

    pos += 2 * k;

    每次处理完一个块之后,pos 向前移动 2k 个位置,这样就可以跳过已经处理过的部分,并准备处理下一个块。

  6. 返回结果:

    return s;

    最后返回经过处理后的字符串。

示例

假设输入字符串为 "abcdefghi"k = 3:

  1. 第一次迭代:

    • pos = 0,反转 "abc",结果变为 "cba"
    • pos 更新为 6 (2 * k = 6)。
  2. 第二次迭代:

    • pos = 6,反转 "ghi",结果变为 "cbadefghi"
    • pos 更新为 12,但此时 pos 已经大于字符串长度,循环结束。

最终输出结果为 "cbadefghi"

时间复杂度与空间复杂度

  • 时间复杂度: O(n),其中 n 是字符串 s 的长度。因为每个字符最多被访问两次(一次正向,一次反向)。
  • 空间复杂度: O(1),除了输入和输出之外没有使用额外的空间。

翻转字符串中的单词

557. 反转字符串中的单词 III - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/reverse-words-in-a-string-iii/description/

class Solution {
public:string reverseWords(string s) {//判断是否为nullptrif(s.empty())return s;int slow = 0,fast = 0,len = s.size();while(fast < len){//先让fast走到空格之前的位置while(fast < len && s[fast] != ' ')fast++;//进行逆置    reverse(s.begin()+slow,s.begin()+fast);fast++;slow = fast;}return s;}};
  1. 检查空字符串

    • 如果输入的字符串 s 是空的,直接返回原字符串。
  2. 初始化

    • 定义两个整数变量 slow 和 fast,初始值都设为 0。这两个变量将作为指针来遍历字符串。
    • 获取字符串 s 的长度,并将其存储在变量 len 中。
  3. 遍历和反转

    • 使用 while 循环遍历整个字符串,直到 fast 指针到达字符串末尾。
    • 在循环内部,再使用一个 while 循环来找到单词的结束位置(即遇到空格或到达字符串末尾)。这通过检查 s[fast] 是否为空格来实现。
    • 找到单词后,使用 std::reverse 函数来反转从 slow 到 fast 之间的字符。这里的 std::reverse 是从 <algorithm> 头文件中导入的,用于反转范围内的元素。
    • 将 fast 增加 1 以跳过单词后的空格(如果有的话)。
    • 将 slow 设置为 fast 的值,以便处理下一个单词。
  4. 返回结果

    • 最终返回修改后的字符串 s

示例:

  • 输入:"the sky is blue"
  • 输出:"ehT yks si eulb"

注意:

  • 此函数不会反转单词的顺序,而是反转每个单词中的字符。例如,输入 "hello world" 的输出将是 "olleh dlrow",而不是 "world hello"。
  • 这个函数没有处理单词间多个空格的情况,也没有处理字符串开头和结尾的空格。如果需要处理这些情况,则需要添加额外的逻辑。

字符串中的第一个唯一字符

387. 字符串中的第一个唯一字符 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/first-unique-character-in-a-string/

class Solution {
public:
//计数排序思想int firstUniqChar(string s) {int arr[26] = {0};for(auto ch : s){// a-a = 0  b -a = 1 c-a = 2arr[ ch - 'a']++;}for(size_t i = 0;i < s.size();i++){if (arr[s[i] - 'a'] == 1)return i;}return -1;}
};

这段代码定义了一个名为 Solution 的类,并且在其中实现了一个名为 firstUniqChar 的方法。这个方法接收一个 std::string 类型的参数 s,并返回第一个不重复出现的字符在字符串中的索引,如果不存在这样的字符则返回 -1

这里是详细的代码分析:

  1. 初始化计数数组

    • 创建一个大小为 26 的整数数组 arr,用于存储每个小写字母出现的次数。数组下标代表字母的位置(例如,'a' 对应下标 0,'b' 对应下标 1,以此类推),数组元素表示该字母出现的次数。
  2. 统计字符出现次数

    • 遍历字符串 s 中的每一个字符 ch
    • 计算 ch 在数组 arr 中对应的下标,这里用 ch - 'a' 来得到该字符与 'a' 之间的偏移量。
    • 将对应下标的计数值增加 1。
  3. 查找第一个唯一字符

    • 再次遍历字符串 s
    • 对于每一个字符 s[i],计算它在数组 arr 中对应的下标。
    • 如果该字符只出现了一次(即 arr[s[i] - 'a'] == 1),则返回该字符的索引 i
  4. 未找到唯一字符

    • 如果遍历完整个字符串都没有找到只出现一次的字符,返回 -1

示例:

  • 输入:"leetcode"

  • 输出:0 (因为 'l' 是第一个只出现一次的字符)

  • 输入:"loveleetcode"

  • 输出:2 (因为 'v' 是第一个只出现一次的字符)

  • 输入:"aabbcc"

  • 输出:-1 (因为没有只出现一次的字符)

注意:

  • 此函数假设输入字符串 s 只包含小写字母。如果输入可能包含大写字母或其他字符,则需要对代码进行相应的调整。
  • 如果输入字符串非常大,这种方法的空间复杂度是 O(1),因为它只需要固定大小的数组来计数,而时间复杂度是 O(n),其中 n 是字符串的长度

字符串最后一个单词的长度

字符串最后一个单词的长度_牛客题霸_牛客网 (nowcoder.com)icon-default.png?t=N7T8https://www.nowcoder.com/practice/8c949ea5f36f422594b306a2300315da?tpId=37&&tqId=21224&rp=5&ru=/activity/oj&qru=/ta/huawei/question-ranking

#include <iostream>
#include <string>
using namespace std;int main() {string str;//这个接口可以指定换行符才读取结束    getline(cin, str,'\n');//利用rfind找最后一个空格size_t pos = str.rfind(' ');//输出长度cout << str.size() - (pos+1) << endl;}
  1. 引入必要的头文件

    • #include <iostream> 引入输入输出流库,使得我们可以使用 std::cin 和 std::cout
    • #include <string> 引入字符串处理库,使得我们可以使用 std::string 类。
  2. 使用命名空间

    • using namespace std; 使得我们可以直接使用 std 命名空间下的标识符,如 coutcin 和 string
  3. 主函数定义

    • int main() 定义了程序的入口点。
  4. 读取输入

    • 定义一个 std::string 类型的变量 str 来存储输入的文本。
    • 使用 getline(cin, str, '\n') 从标准输入读取一行文本,直到遇到换行符 \n。这使得我们可以读取包含空格的字符串。
  5. 查找最后一个空格的位置

    • 使用 str.rfind(' ') 查找字符串 str 中最后一个空格的位置。rfind 方法返回最后一个匹配字符的位置,如果没有找到匹配的字符,则返回 std::string::npos
  6. 计算并输出最后一个单词的长度

    • 计算从最后一个空格到最后一个字符的距离,即最后一个单词的长度。这里使用 str.size() - (pos + 1) 来计算长度。
    • 如果 pos 为 std::string::npos(即没有找到空格),则 (pos + 1) 会被转换为一个非常大的数值,因此 str.size() - (pos + 1) 会得到一个负数,这会导致运行时错误。为了避免这种情况,我们需要检查 pos 是否为 std::string::npos
    • 使用 std::cout 输出最后一个单词的长度。

示例:

  • 输入:"Hello World"
  • 输出:5 (因为最后一个单词是 "World",长度为 5)

验证回文

125. 验证回文串 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/valid-palindrome/

class Solution {
public://判断是否为所需字符bool isletter(char ch){return (ch >= '0' && ch <= '9') ||(ch >= 'a' && ch <= 'z')||(ch >= 'A' && ch <= 'Z');}bool isPalindrome(string s) {for (auto& ch : s){//这里将所有的大写转换为小写if(ch >= 'A' && ch <= 'Z')ch += 32;}int begin = 0,end = s.size()-1;//这两个循环是为了避开除了字符之外的数据while(begin < end){while(begin < end  && !isletter(s[begin])){++begin;}while(begin < end && !isletter(s[end])){--end;}//判断左右是否是相等的,快排的思想if(s[begin] != s[end]){return false;}++begin;--end;}//排除所有可能就说明是回文return true;}
};
  1. 辅助函数 isletter

    • 这个函数接受一个字符 ch,并检查它是否是一个字母或数字。
    • 如果 ch 是一个小写字母、大写字母或数字,则返回 true;否则返回 false
  2. 主函数 isPalindrome

    • 首先,遍历字符串 s 的每个字符 ch 并将其转换为小写(如果它是大写字母的话)。
    • 初始化两个指针 begin 和 end,分别指向字符串的开始和结束位置。
    • 使用两个 while 循环来逐步向中心逼近,同时跳过非字母和非数字的字符。
    • 比较 begin 和 end 指针所指向的字符是否相同。如果不相同,则立即返回 false 表示不是回文。
    • 当 begin 和 end 相遇或者交叉时,说明已经检查完所有字符,此时返回 true 表示是回文。

示例:

  • 输入:"A man, a plan, a canal: Panama"

  • 输出:true (因为忽略标点符号和空格后,该字符串是一个回文)

  • 输入:"race a car"

  • 输出:false (因为忽略标点符号和空格后,该字符串不是一个回文)


把字符串转换成整数

LCR 192. 把字符串转换成整数 (atoi) - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/ba-zi-fu-chuan-zhuan-huan-cheng-zheng-shu-lcof/description/

class Solution {
public:int myAtoi(string s) {long long ans = 0;//检查空格(确定起始位置)int pos = 0;while(pos < s.length() && s[pos] == ' ') pos++;//判断是否全是空格if(pos == s.length() && s[pos] == ' ')return 0;//判断正负int sym = 1;if(s[pos] == '-')sym = -1,pos++;else if(s[pos] == '+')pos++;//进行转换计算for(int i = pos;i < s.length() && isdigit(s[i]); i++ ){//判断是否是十进制数ans = ans * 10 + (sym * (s[i] - '0'));//判断是否大于最大数/小于最小数(避免越界)if(ans > 0 && ans >= INT_MAX)return INT_MAX;if(ans < 0 && ans <= INT_MIN)return INT_MIN;}return ans;}
};
  1. 初始化和检查空格

    • 定义一个 long long 类型的变量 ans 用来存储最终的转换结果。
    • 定义一个整数变量 pos 用来记录字符串中有效字符的起始位置,默认为 0。
    • 使用 while 循环来跳过字符串开头的空格,直到遇到非空格字符或到达字符串末尾。
  2. 检查字符串是否全为空格

    • 如果字符串全部由空格组成,那么返回 0。
  3. 判断正负号

    • 如果在 pos 位置遇到了负号 -,则设置 sym 为 -1 并将 pos 加 1。
    • 如果在 pos 位置遇到了正号 +,则保持 sym 为 1(默认值)并将 pos 加 1。
  4. 转换计算

    • 使用 for 循环遍历从 pos 开始的字符,直到遇到非数字字符或到达字符串末尾。
    • 对于每一个数字字符,首先检查它是否为有效的十进制数字(使用 isdigit 函数)。
    • 将当前字符减去 '0' 来获取其数值,并乘以 sym 来决定正负。
    • 更新 ans 的值,使其乘以 10 后加上当前数字的值。
    • 在每次迭代中检查 ans 是否超过了 INT_MAX 或 INT_MIN,以避免溢出。
  5. 返回结果

    • 返回 ans 的值。

示例:

  • 输入:"42"

  • 输出:42

  • 输入:" -42"

  • 输出:-42

  • 输入:"4193 with words"

  • 输出:4193

  • 输入:"words and 987"

  • 输出:0

  • 输入:"-91283472332"

  • 输出:-2147483648 (因为超过了 INT_MIN


字符串相加

415. 字符串相加 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/add-strings/description/

class Solution {
public:string addStrings(string num1, string num2) {// 采用进位法int end1 = num1.size() - 1, end2 = num2.size() - 1;// 存储进位数int next = 0;//存储最后的和string sum;while (end1 >= 0 || end2 >= 0) {// 转换为整数int val1 = end1 >= 0 ?num1[end1--] - '0' : 0;int val2 = end2 >= 0 ? num2[end2--] - '0' : 0;int ret = val1 + val2 + next;next = ret / 10; // 取进位数ret = ret % 10;  // 取进位数的和// 头插法//sum.insert(sum.begin(), ret + '0');// 尾插法sum += (ret+'0');}// 判断是否还有进位数if (next == 1) {//sum.insert(sum.begin(), '1');sum += '1';}//STL逆置接口reverse(sum.begin(),sum.end());return sum;}
};
  1. 初始化

    • 定义两个整数变量 end1 和 end2,分别初始化为 num1 和 num2 的最后一个字符的位置。
    • 定义一个整数变量 next 来存储进位。
    • 定义一个 std::string 类型的变量 sum 来存储结果。
  2. 逐位相加

    • 使用 while 循环来逐位相加 num1 和 num2
    • 对于 num1 和 num2 的每一位,先将其从字符转换为整数(通过减去 '0')。
    • 将两个整数以及当前的进位 next 相加。
    • 更新 next 为当前和除以 10 的商(即新的进位)。
    • 将当前和对 10 取模的结果转换回字符,并追加到 sum 字符串的末尾。
    • 继续处理直到 end1 和 end2 都小于 0,即已经处理完两个字符串的所有字符。
  3. 处理最后的进位

    • 如果 next 不为 0,则表示还有进位需要加入到结果中。将 next 转换为字符 '1' 并追加到 sum 字符串的末尾。
  4. 逆置结果字符串

    • 使用 std::reverse 函数逆置 sum 字符串,因为我们在逐位相加的过程中是从低位到高位进行操作的。
  5. 返回结果

    • 返回逆置后的 sum 字符串作为最终结果。

示例:

  • 输入:"11""123"
  • 输出:"134"

字符串相乘

43. 字符串相乘 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/multiply-strings/description/

class Solution {
public:string multiply(string num1, string num2) {//获取长度int n = num1.length(); int m = num2.length();vector<int> v(n+m,0);//定义数组长度(m+n)//不进位计算for(int i = 0; i < n ; i++){for(int j = 0; j < m;   j++){int x = num1[n - i - 1] - '0';int y = num2[m - j - 1] - '0';v[i + j] += x * y;}}//进位处理for(int i = 0,sym = 0 ;i < v.size(); i++ ){v[i] += sym;sym = v[i] / 10;v[i] %= 10;}//最后转为字符返回string ret;for(int i = v.size() - 1;i >= 0;i--){if(ret.empty() && v[i] == 0)continue;//这里必须处理,因为这个数的后面都是初始化的0,不需要存ret += (v[i] + '0');}return ret.empty() ? "0" : ret;}};
  1. 初始化

    • 获取 num1 和 num2 的长度分别为 n 和 m
    • 定义一个整数向量 v,其长度为 n + m,并初始化为 0。这个向量将用于存储乘积过程中的各个位的值。
  2. 逐位相乘

    • 使用两层嵌套的 for 循环来逐位相乘 num1 和 num2
    • 对于 num1 和 num2 的每一位,先将其从字符转换为整数(通过减去 '0')。
    • 将两个整数相乘,并将结果存储在 v 中相应的位置上。注意这里使用了 n - i - 1 和 m - j - 1 来从右向左访问字符串中的字符。
  3. 进位处理

    • 使用一个 for 循环来处理进位。对于 v 中的每一个元素,如果其值大于等于 10,则需要进行进位处理。
    • 进位处理时,将当前值除以 10 来获取进位,然后将当前值对 10 取模来获取余数(即新值)。
  4. 转换为字符串

    • 使用一个 for 循环从 v 的末尾开始遍历,将每个元素转换为字符并追加到结果字符串 ret 中。
    • 如果 ret 还为空并且当前值为 0,则跳过该值。这是因为乘积的最高位可能是 0,如果存在这样的 0,就不应该加入到结果中。
    • 如果最终 ret 为空,说明结果为 0,返回字符串 "0"
  5. 返回结果

    • 返回结果字符串 ret

示例:

  • 输入:"123""456"
  • 输出:"56088"

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • springboot rbac Security
  • 向量数据库(二):Qdrant
  • 2024网络安全学习路线 非常详细 推荐学习
  • Kafka面试三道题
  • 感知融合算法学习1
  • 讲一下我对C语言指针入门过程
  • Web3 开发教程
  • IP 泄露: 原因与避免方法
  • 27-《木芙蓉》
  • docker环境安装kafka/Flink/clickhouse镜像
  • spring 不同service事务如何传递
  • Vue3自研开源Tree组件:人性化的拖拽API设计
  • 新手小白要如何自学黑客技术,看这篇就够了!
  • SpringBoot内置Tomcat启动原理
  • 装饰大师——装饰模式(Python实现)
  • “寒冬”下的金三银四跳槽季来了,帮你客观分析一下局面
  • 「前端」从UglifyJSPlugin强制开启css压缩探究webpack插件运行机制
  • 【技术性】Search知识
  • IDEA常用插件整理
  • laravel with 查询列表限制条数
  • 安装python包到指定虚拟环境
  • 道格拉斯-普克 抽稀算法 附javascript实现
  • 对超线程几个不同角度的解释
  • 多线程 start 和 run 方法到底有什么区别?
  • 反思总结然后整装待发
  • 关于extract.autodesk.io的一些说明
  • 浅谈web中前端模板引擎的使用
  • 设计模式走一遍---观察者模式
  • 算法系列——算法入门之递归分而治之思想的实现
  • 听说你叫Java(二)–Servlet请求
  • 突破自己的技术思维
  • - 语言经验 - 《c++的高性能内存管理库tcmalloc和jemalloc》
  • gunicorn工作原理
  • 如何在招聘中考核.NET架构师
  • #etcd#安装时出错
  • #考研#计算机文化知识1(局域网及网络互联)
  • (echarts)echarts使用时重新加载数据之前的数据存留在图上的问题
  • (ibm)Java 语言的 XPath API
  • (分布式缓存)Redis持久化
  • (附源码)springboot“微印象”在线打印预约系统 毕业设计 061642
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
  • .env.development、.env.production、.env.staging
  • .NET Core WebAPI中封装Swagger配置
  • .net 微服务 服务保护 自动重试 Polly
  • .Net 知识杂记
  • .net实现头像缩放截取功能 -----转载自accp教程网
  • .net通用权限框架B/S (三)--MODEL层(2)
  • .net最好用的JSON类Newtonsoft.Json获取多级数据SelectToken
  • @Async 异步注解使用
  • [ 隧道技术 ] 反弹shell的集中常见方式(二)bash反弹shell
  • [2019.2.28]BZOJ4033 [HAOI2015]树上染色
  • [23] 4K4D: Real-Time 4D View Synthesis at 4K Resolution
  • [⑧ADRV902x]: Digital Pre-Distortion (DPD)学习笔记
  • [Android 13]Input系列--获取触摸窗口