1.仅仅反转字母
像上述的题我们应该怎么思考呢?我们常规的解法就是双指针一个从头一个从尾,不是字母就加加或者是减减,脑子里有了一个大概的模型了吗?请看正确解法:
cpp
class Solution {
public:
string reverseOnlyLetters(string s) {
if(s.empty())
return s;
int n1=0,n2=s.size()-1;
while(n1<n2)
{
while(n1<n2&&!isalpha(s[n1]))
n1++;
while(n1<n2&&!isalpha(s[n2]))
n2--;
swap(s[n1++],s[n2--]);
}
return s;
}
};
让我们来解析一下这段代码:
1: class Solution :定义了一个解决方案类。
2: reverseOnlyLetters 函数:用于反转字符串中仅字母部分。
3: 首先进行边界检查,如果字符串为空则直接返回空字符串。
4: 然后定义两个指针 n1 (起始指针)和 n2 (结束指针),初始分别指向字符串的开头和结尾。
5: 通过两个嵌套的 while 循环,分别找到第一个指针指向的非字母位置和第二个指针指向的非字母位置,跳过这些非字母字符。
6: 当找到两个指针都指向字母时,进行交换操作,并将两个指针同时移动一位( n1++ 和 n2-- )。
7: 这样通过不断交换字母位置,最终实现只反转字母部分的效果,最后返回处理后的字符串。
2.字符串中第一个唯一字符
像上述的题我们又应该怎么思考呢?,应该很容易想到我们之前学到的一种排序方法---计数排序,那么这道题也有着类似的结构,请看正确解法:
cpp
class Solution {
public:
int firstUniqChar(string s) {
int count[26]={0};
for(auto ch:s)
count[ch-'a']++;
for(int i=0;i<s.size();i++)
{
if(count[s[i]-'a']==1)
return i;
}
return -1;
}
};
让我们来解析一下这段代码:
1: class Solution :定义了解决方案类。
2: firstUniqChar 函数:目的是找出字符串中第一个不重复的字符的索引。
3: 首先定义了一个大小为 26 的整数数组 count ,用于统计每个字母出现的次数。通过遍历字符串 s ,将字符转换为相对应的索引( ch - 'a' ),然后将该索引对应的计数 加 1。
4: 接着再次遍历字符串,对于每个字符,检查其在 count 数组中的计数 是否为 1,如果是,则说明该字符是不重复的,立即返回其索引 i 。
5: 如果遍历完整个字符串都没有找到不重复的字符,则返回 -1 。
3.字符串最后一个单词的长度
在上述问题中,要去找最后一个单词的长度,好像只需要找到最后一个空格的位置即可,那么思路形成,请看正确代码:
cpp
#include <iostream>
using namespace std;
int main()
{
string line;
getline(cin,line);
size_t pos=line.rfind(' ');
cout<<line.size()-pos-1<<endl;
}
让我们来解析一下这段代码:
1: string line; :定义了一个字符串变量 line 。
2: getline(cin, line); :从标准输入(键盘)读取一行文本到 line 中。
3: size_t pos = line.rfind(' '); :使用 rfind 函数在 line 中查找最后一个空格字符的位置,并将其位置存储在 pos 变量中。
4: cout << line.size() - pos - 1 << endl; :计算并输出字符串 line 的长度减去最后一个空格位置再减 1 的值,实际上就是输出从最后一个空格到字符串结尾的字符个数,即最后一个单词的长度。
4.验证回文串
在上述问题中,要去判断一个字符串是否是回文串,很容易想到的方法就是双指针啦,一前一后去走,那么请看示例代码:
cpp
class Solution {
public:
bool isPalindrome(string s) {
for(auto& ch:s)
{
if(ch>='A'&&ch<='Z')
ch+=32;
}
int n1=0,n2=s.size()-1;
while(n1<n2)
{
while(n1<n2&&!isalnum(s[n1]))
n1++;
while(n1<n2&&!isalnum(s[n2]))
n2--;
if(s[n1]!=s[n2])
return false;
n1++;
n2--;
}
return true;
}
};
让我们来解析一下这段代码:
1: class Solution :定义了一个名为 Solution 的类。
2: isPalindrome 函数:这是该类的一个方法,用于判断给定的字符串 s 是否为回文。
3: 首先通过遍历字符串 s ,将其中的大写字母转换为小写字母。
4: 然后定义两个指针 n1 (起始位置)和 n2 (末尾位置)。
5: 通过两个嵌套的 while 循环,分别跳过字符串开头和结尾处的非字母和数字字符。
6: 接着比较对应位置的字符,如果不相等则直接返回 false ,表示不是回文;如果相等则两个指针分别向前和向后移动一位。
7: 如果整个遍历过程中都没有发现不相等的情况,则最后返回 true ,表示是回文。
5.字符串相加
在上述问题中,一般思路:
-
确定相加顺序:明确是将两个或多个字符串按什么顺序连接起来。
-
逐个字符处理:从第一个字符串的开头开始,依次取出字符,然后与另一个字符串相应位置的字符进行连接操作。
-
考虑特殊情况:比如处理字符串可能为空的情况,或者对于一些特殊字符或格式要求进行特殊处理。
-
构建结果字符串:将每次连接得到的字符逐步添加到结果字符串中,直到完成所有字符串的相加操作。
让我们来解析一下这段代码:
1: addStrings 函数用于将两个字符串表示的数字进行相加。
2: n1 和 n2 分别记录两个字符串的当前索引位置,从末尾开始。
3: val1 和 val2 分别表示从两个字符串当前位置取出的数字值(如果索引有效则取对应字符转换为数字,否则为 0)。
4: 在循环中,只要还有未处理完的数字或者有进位( next 不为 0),就继续进行计算。计算当前两个数字和进位的和 sum ,并更新进位 next 为和除以 10 的商,然后将和除以 10 的余数转换为字符添加到 str 中。
5: 最后通过 reverse 函数反转 str 得到最终的结果字符串。
6:反转字符串(二)
在上述问题中,涉及到多次翻转,那么就很容易想到循环了,再结合使用开头和结尾的迭代器,问题就迎刃而解了,那么请看示例代码:
cpp
class Solution {
public:
string reverseStr(string s, int k) {
int n = s.size();
for (int i = 0; i < n; i += 2 * k) {
reverse(s.begin() + i, s.begin() + min(i + k, n));
}
return s;
}
};
让我们来解析一下这段代码:
1: reverseStr 方法接受一个字符串 s 和一个整数 k 。
2: n 表示字符串 s 的长度。
3: 通过一个循环,从索引 0 开始,每次以步长 2k 前进。
4: 在每次循环中,对从当前索引 i 到 i+k (如果 i+k 超过字符串长度则到字符串末尾)的子串进行反转操作,使用 reverse 函数。
5: 最后返回反转后的字符串 s 。这个方法的作用是按照每 2k 个字符为一组,前 k 个字符进行反转。
7反转字符串中的单词
在上述问题中,只要记住这段话中的空格的位置,然后分区间进行反转,问题也就迎刃而解了;那么请看示例代码:
cpp
class Solution {
public:
string reverseWords(string s) {
size_t pos1=0,pos2=0;
while(pos2!=s.rfind(' '))
{
pos2=s.find(' ',pos1);
reverse(s.begin()+pos1,s.begin()+pos2);
pos1=pos2+1;
}
reverse(s.begin()+pos2+1,s.end());
return s;
}
};
让我们来解析一下这段代码:
1: reverseWords 函数用于反转字符串 s 中的每个单词。
2: pos1 和 pos2 用于标记单词的起始和结束位置。
3: 通过一个循环,不断寻找空格来确定单词的边界。当 pos2 不等于字符串中最后一个空格的位置时,就对从 pos1 到 pos2 的子串进行反转。然后更新 pos1 为 pos2+1 ,准备寻找下一个单词。
4: 当循环结束后,再对最后一个单词(从 pos2+1 到字符串末尾)进行反转。
5: 最后返回处理后的字符串,此时每个单词都被反转了。
到此我们只是简单的介绍了一下STL中string的相关习题~,后续我们会一一展开学习的,希望这篇博客能给您带来一些启发和思考!那我们下次再一起探险喽,欢迎在评论区进行讨论~~~