leetcode题目:151.翻转字符串里的单词
给定一个字符串,逐个翻转字符串中的每个单词。
说明:
- 无空格字符构成一个 单词 。
- 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
- 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
思路
将整个字符串都反转过来,那么单词的顺序指定是倒序了,只不过单词本身也倒叙了,那么再把单词反转一下,单词就正过来了。
所以解题思路如下:
- 移除多余空格
- 将整个字符串反转
- 将每个单词反转
如图:
C++代码
class solution
{
public:
//反转区间内的字符
void reverse(string& s, int begin, int end)
{
for (int i = begin, j = end; i < j; i++, j--)
{
swap(s[i], s[j]);
}
}
//移除字符串中的多余空格,使用双指针法
//为方便理解,参考字符串s = "__Bob____Loves__Alice___", 这里以下划线表示空格
void removeExtraSpace(string& s)
{
int slow = 0, fast = 0;
//去掉字符串前面的空格,参考字符串中的前两个下划线
while (s.size() > 0 && fast < s.size() && s[fast] == ' ')
{
fast++;
}
//退出while后 fast = 2, slow = 0
//去掉字符串中间的空格
for (; fast < s.size(); fast++)
{
if (fast - 1 > 0 && s[fast] == s[fast - 1] && s[fast] == ' ')
{
continue;
}
else
{
s[slow++] = s[fast];
}
}
//for 循环后slow = 15, fast = 21。
//去掉字符串后面的空格
if (slow - 1 > 0 && s[slow - 1] == ' ')
{
s.resize(slow - 1);
}
else
{
s.resize(slow);
}
//去除空格后的字符串s = "Bob_Loves_Alice"; s.size() = 15;
}
//正戏:反转字符串里的单词
string reverseWords(string s)
{
//去掉多余空格
removeExtraSpace(s);
//反转整个字符串
reverse(s, 0, s.size() - 1);
int start = 0; //用来标记字符串中单词的起始位置
int end = 0; //用来标记字符串中单词的结束位置
int entry = false; //用来标记是否进入单词
//下面开始反转字符串中的单词
//参考字符串:s = "Bob_Loves_Alice";
for (int i = 0; i < s.size(); i++)
{
if (!entry && (s[i] != ' ' && s[i - 1] == ' ')) //entry == false 说明为进入单词,即还没有记录单词起始终止位置。单词起始标志:s[i] != ' ' && s[i - 1] == ' '
{
start = i; //记录单词起始位置
entry = true; //标识已进入单词,即开始记录位置
}
if (entry && (s[i] == ' ' && s[i - 1] != ' ')) //单词结束标志:s[i] == ' ' && s[i - 1] != ' '
{
end = i - 1; //记录单词结束位置
entry = false; //结束单词区间
reverse(s, start, end); //反转该单词
}
//最后一个单词后面没有空格,所以需要单独处理
if (entry && s[i] != ' ' && (i == s.size() - 1))
{
end = i; //确定最后一个单词结束位置
entry = fale; //结束单词区间
reverse(s, start, end); //反转最后一个单词
}
}
//最后返回反转后的字符串
return s;
}
};
总结
这道题目可以说是综合考察了字符串的多种操作:移除多余空格(移除字符串中元素)、反转整个字符串、分割单词并局部反转。
而且没有使用额外的辅助空间,直接在原字符串上操作。
所以后面reverseWords(string s)的参数类型是string 而不是string&了,和链表一样(使用临时指针操作链表)的道理。
原文:字符串:花式反转还不够!