题目链接:仅仅反转字母
解题思路:
这种反转字符的题目我第一个想到的方法就是:双指针
一个指针在前start,一个指针在后back,
如果指针所指向的位置的值是字母,那么两个指针位置的值就进行交换,
如果不是,则该指针就往下走一位,直到所指向的位置的值是字母。
ok思路有了,现在的问题就是:
1.怎么表示前后两个指针
2.怎么让这两个指针动起来?什么时候又停下?
3.用什么方法来判断该位置是不是字母?
好,我们一个一个来看:
第一个问题:怎么表示前后两个指针
看过我【C++】String类这篇文章的都知道,访问string我们有三种方式:
1.[ ]+下标
2.迭代器
3.范围for
既然我们想要表示string的前后两个位置,我这里选择的是迭代器:
string::iterator start = s.begin();
string::iterator back = s.end()-1;
注意begin和end是左闭右开区间[……),所以back这里要减1才能指向最后一个位置。
2.怎么让这两个指针动起来?什么时候又停下?
我们可以用while循环,start++,back--
同时要保持start<back
3.用什么方法来判断该位置是不是字母?
可以用isalpha函数来判断,
isalpha
函数是一个标准库函数,用于检查给定的字符是否是字母。
- 如果
c
是一个字母(大写或小写),则返回非零值(通常是1
)。 - 如果
c
不是字母,则返回0
。
拓展:
但是,它有个要求,就是它希望我们给它的字符对应的数字要是0到255之间的,这样它才能正确地判断。
问题来了,如果我们直接给一个字符给
isalpha
,而这个字符对应的数字在ASCII编码里是负数(因为char
类型在有些电脑里是可以表示负数的),那么isalpha
就可能会出错,因为它不认识这个负数对应的字符是什么。所以,为了避免这个问题,我们要先把这个字符转换成一个无符号的数字,确保它是0到255之间的。这就是
static_cast<unsigned char>(*back)
的作用。它就像是一个翻译,把有符号的字符翻译成无符号的数字,这样isalpha
就能正确地识别字符了。
当然,这道题,不用加static_cast<unsigned char>(*back)也行
while (start < back)
{
while(start < back&&(!isalpha(static_cast<unsigned char>(*start))))
start++;
while (start < back&&(!isalpha(static_cast<unsigned char>(*back))))
back--;
swap(*start, *back);
start++;
back--;
}
所以整体代码为:
class Solution {
public:
string reverseOnlyLetters(string s) {
string::iterator start = s.begin();
string::iterator back = s.end()-1;
while (start < back)
{
while(start < back&&(!isalpha(static_cast<unsigned char>(*start))))
start++;
while (start < back&&(!isalpha(static_cast<unsigned char>(*back))))
back--;
swap(*start, *back);
start++;
back--;
}
return s;
};
};