翻转字符串
344. 反转字符串 - 力扣(LeetCode)
https://leetcode.cn/problems/reverse-string/
class Solution { public: void reverseString(vector<char>& s) { reverse(s.begin(),s.end());//直接上逆置接口 } };
函数签名:
void reverseString(vector<char>& s);这个函数不返回任何值 (
void),并且接受一个vector<char>类型的引用s作为输入参数。调用
std::reverse函数:reverse(s.begin(), s.end());使用标准库中的
std::reverse函数来反转vector<char>中的元素。s.begin()返回指向向量第一个元素的迭代器,s.end()返回指向向量最后一个元素之后的一个位置的迭代器。因此,std::reverse会将s中的所有元素进行反转。
翻转字符串||
541. 反转字符串 II - 力扣(LeetCode)
https://leetcode.cn/problems/reverse-string-ii/description/
问题描述
给定一个字符串
s和一个整数k,任务是反转每2k个字符中的前k个字符。如果剩余字符不足k个,则将这些字符全部反转。示例
- 输入:
s = "abcdefghi", k = 3- 输出:
"cbadefghi"解释
- 字符串按长度
2k划分为几个部分。- 对于每个部分,前
k个字符被反转。- 部分中剩余的字符(如果有)保持不变。
- 将所有部分串联起来形成结果。
代码解释
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; } };
函数签名:
string reverseStr(string s, int k);这个函数返回一个字符串,并接受一个字符串
s和一个整数k作为输入参数。变量初始化:
int pos = 0; // 开始反转或向前移动的位置
pos是一个整型变量,用来记录当前处理到字符串中的哪个位置。初始时pos被设置为0,即从字符串的起始位置开始处理。循环处理字符串:
while (pos < s.size()) { // ... }使用
while循环遍历整个字符串,直到pos超过字符串的长度。条件判断与反转操作:
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到字符串结尾的所有字符。更新位置:
pos += 2 * k;每次处理完一个块之后,
pos向前移动2k个位置,这样就可以跳过已经处理过的部分,并准备处理下一个块。返回结果:
return s;最后返回经过处理后的字符串。
示例
假设输入字符串为
"abcdefghi"且k = 3:
第一次迭代:
pos = 0,反转"abc",结果变为"cba"。pos更新为6(2 * k = 6)。第二次迭代:
pos = 6,反转"ghi",结果变为"cbadefghi"。pos更新为12,但此时pos已经大于字符串长度,循环结束。最终输出结果为
"cbadefghi"。时间复杂度与空间复杂度
- 时间复杂度: O(n),其中 n 是字符串
s的长度。因为每个字符最多被访问两次(一次正向,一次反向)。- 空间复杂度: O(1),除了输入和输出之外没有使用额外的空间。
翻转字符串中的单词
557. 反转字符串中的单词 III - 力扣(LeetCode)
https://leetcode.cn/problems/reverse-words-in-a-string-iii/description/
class Solution { public: string reverseWords(string s) { //判断是否为nullptr if(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; } };
检查空字符串:
- 如果输入的字符串
s是空的,直接返回原字符串。初始化:
- 定义两个整数变量
slow和fast,初始值都设为 0。这两个变量将作为指针来遍历字符串。- 获取字符串
s的长度,并将其存储在变量len中。遍历和反转:
- 使用
while循环遍历整个字符串,直到fast指针到达字符串末尾。- 在循环内部,再使用一个
while循环来找到单词的结束位置(即遇到空格或到达字符串末尾)。这通过检查s[fast]是否为空格来实现。- 找到单词后,使用
std::reverse函数来反转从slow到fast之间的字符。这里的std::reverse是从<algorithm>头文件中导入的,用于反转范围内的元素。- 将
fast增加 1 以跳过单词后的空格(如果有的话)。- 将
slow设置为fast的值,以便处理下一个单词。返回结果:
- 最终返回修改后的字符串
s。示例:
- 输入:"the sky is blue"
- 输出:"ehT yks si eulb"
注意:
- 此函数不会反转单词的顺序,而是反转每个单词中的字符。例如,输入 "hello world" 的输出将是 "olleh dlrow",而不是 "world hello"。
- 这个函数没有处理单词间多个空格的情况,也没有处理字符串开头和结尾的空格。如果需要处理这些情况,则需要添加额外的逻辑。
字符串中的第一个唯一字符
387. 字符串中的第一个唯一字符 - 力扣(LeetCode)
https://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 = 2 arr[ 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。这里是详细的代码分析:
初始化计数数组:
- 创建一个大小为 26 的整数数组
arr,用于存储每个小写字母出现的次数。数组下标代表字母的位置(例如,'a' 对应下标 0,'b' 对应下标 1,以此类推),数组元素表示该字母出现的次数。统计字符出现次数:
- 遍历字符串
s中的每一个字符ch。- 计算
ch在数组arr中对应的下标,这里用ch - 'a'来得到该字符与'a'之间的偏移量。- 将对应下标的计数值增加 1。
查找第一个唯一字符:
- 再次遍历字符串
s。- 对于每一个字符
s[i],计算它在数组arr中对应的下标。- 如果该字符只出现了一次(即
arr[s[i] - 'a'] == 1),则返回该字符的索引i。未找到唯一字符:
- 如果遍历完整个字符串都没有找到只出现一次的字符,返回
-1。示例:
输入:
"leetcode"输出:
0(因为'l'是第一个只出现一次的字符)输入:
"loveleetcode"输出:
2(因为'v'是第一个只出现一次的字符)输入:
"aabbcc"输出:
-1(因为没有只出现一次的字符)注意:
- 此函数假设输入字符串
s只包含小写字母。如果输入可能包含大写字母或其他字符,则需要对代码进行相应的调整。- 如果输入字符串非常大,这种方法的空间复杂度是 O(1),因为它只需要固定大小的数组来计数,而时间复杂度是 O(n),其中 n 是字符串的长度
字符串最后一个单词的长度
字符串最后一个单词的长度_牛客题霸_牛客网 (nowcoder.com)
https://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; }
引入必要的头文件:
#include <iostream>引入输入输出流库,使得我们可以使用std::cin和std::cout。#include <string>引入字符串处理库,使得我们可以使用std::string类。使用命名空间:
using namespace std;使得我们可以直接使用std命名空间下的标识符,如cout、cin和string。主函数定义:
int main()定义了程序的入口点。读取输入:
- 定义一个
std::string类型的变量str来存储输入的文本。- 使用
getline(cin, str, '\n')从标准输入读取一行文本,直到遇到换行符\n。这使得我们可以读取包含空格的字符串。查找最后一个空格的位置:
- 使用
str.rfind(' ')查找字符串str中最后一个空格的位置。rfind方法返回最后一个匹配字符的位置,如果没有找到匹配的字符,则返回std::string::npos。计算并输出最后一个单词的长度:
- 计算从最后一个空格到最后一个字符的距离,即最后一个单词的长度。这里使用
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)
https://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; } };
辅助函数
isletter:
- 这个函数接受一个字符
ch,并检查它是否是一个字母或数字。- 如果
ch是一个小写字母、大写字母或数字,则返回true;否则返回false。主函数
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)
https://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; } };
初始化和检查空格:
- 定义一个
long long类型的变量ans用来存储最终的转换结果。- 定义一个整数变量
pos用来记录字符串中有效字符的起始位置,默认为 0。- 使用
while循环来跳过字符串开头的空格,直到遇到非空格字符或到达字符串末尾。检查字符串是否全为空格:
- 如果字符串全部由空格组成,那么返回 0。
判断正负号:
- 如果在
pos位置遇到了负号-,则设置sym为 -1 并将pos加 1。- 如果在
pos位置遇到了正号+,则保持sym为 1(默认值)并将pos加 1。转换计算:
- 使用
for循环遍历从pos开始的字符,直到遇到非数字字符或到达字符串末尾。- 对于每一个数字字符,首先检查它是否为有效的十进制数字(使用
isdigit函数)。- 将当前字符减去
'0'来获取其数值,并乘以sym来决定正负。- 更新
ans的值,使其乘以 10 后加上当前数字的值。- 在每次迭代中检查
ans是否超过了INT_MAX或INT_MIN,以避免溢出。返回结果:
- 返回
ans的值。示例:
输入:
"42"输出:
42输入:
" -42"输出:
-42输入:
"4193 with words"输出:
4193输入:
"words and 987"输出:
0输入:
"-91283472332"输出:
-2147483648(因为超过了INT_MIN)
字符串相加
415. 字符串相加 - 力扣(LeetCode)
https://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; } };
初始化:
- 定义两个整数变量
end1和end2,分别初始化为num1和num2的最后一个字符的位置。- 定义一个整数变量
next来存储进位。- 定义一个
std::string类型的变量sum来存储结果。逐位相加:
- 使用
while循环来逐位相加num1和num2。- 对于
num1和num2的每一位,先将其从字符转换为整数(通过减去'0')。- 将两个整数以及当前的进位
next相加。- 更新
next为当前和除以 10 的商(即新的进位)。- 将当前和对 10 取模的结果转换回字符,并追加到
sum字符串的末尾。- 继续处理直到
end1和end2都小于 0,即已经处理完两个字符串的所有字符。处理最后的进位:
- 如果
next不为 0,则表示还有进位需要加入到结果中。将next转换为字符'1'并追加到sum字符串的末尾。逆置结果字符串:
- 使用
std::reverse函数逆置sum字符串,因为我们在逐位相加的过程中是从低位到高位进行操作的。返回结果:
- 返回逆置后的
sum字符串作为最终结果。示例:
- 输入:
"11","123"- 输出:
"134"
字符串相乘
43. 字符串相乘 - 力扣(LeetCode)
https://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; } };
初始化:
- 获取
num1和num2的长度分别为n和m。- 定义一个整数向量
v,其长度为n + m,并初始化为 0。这个向量将用于存储乘积过程中的各个位的值。逐位相乘:
- 使用两层嵌套的
for循环来逐位相乘num1和num2。- 对于
num1和num2的每一位,先将其从字符转换为整数(通过减去'0')。- 将两个整数相乘,并将结果存储在
v中相应的位置上。注意这里使用了n - i - 1和m - j - 1来从右向左访问字符串中的字符。进位处理:
- 使用一个
for循环来处理进位。对于v中的每一个元素,如果其值大于等于 10,则需要进行进位处理。- 进位处理时,将当前值除以 10 来获取进位,然后将当前值对 10 取模来获取余数(即新值)。
转换为字符串:
- 使用一个
for循环从v的末尾开始遍历,将每个元素转换为字符并追加到结果字符串ret中。- 如果
ret还为空并且当前值为 0,则跳过该值。这是因为乘积的最高位可能是 0,如果存在这样的 0,就不应该加入到结果中。- 如果最终
ret为空,说明结果为 0,返回字符串"0"。返回结果:
- 返回结果字符串
ret。示例:
- 输入:
"123","456"- 输出:
"56088"




![[GYCTF2020]FlaskApp (pin码,jinja2绕过注入)](https://i-blog.csdnimg.cn/direct/59e01e83ed654d1389e3e9a488ce6b81.png)














