一、541. 反转字符串II
class Solution {
public:
string reverseStr(string s, int k) {
//先找区间 注意区间处理
for(int i=0;i<s.size();i+=(2*k))
{
if(i+k<=s.size())
{
reverse(s.begin()+i, s.begin()+i+k);
}
else
{
reverse(s.begin()+i, s.end());
}
}
return s;
}
};
注意点: 这里很巧妙的是,区间的处理,让i以两倍的k来遍历,相当于每2k个长度处理一次
二、剑指 Offer 05. 替换空格
class Solution {
public:
string replaceSpace(string s) {
int count = 0;//统计空格的个数
int oldSize = s.size();//原字符串长度
//统计空格个数
for(int i=0;i<oldSize;i++)
{
if(s[i]==' ') count++;
}
//扩展大小
s.resize(oldSize+count*2);
//插入字符
int newSize = s.size();
for(int i=oldSize-1,j=newSize-1;i<j;i--,j--)
{
if(s[i]!=' ')
{
s[j]=s[i];
}
else
{
s[j] = '0';
s[j-1] = '2';
s[j-2] = '%';
j -=2;//跳过添加字符的位置 才能和i对应上
}
}
return s;
}
};
注意点:
- 要统计空格的个数,count;原字符串的大小oldSize
- 根据空格的个数,扩展原字符串的大小。%20占三个字符,空格本来占有一个,因此要增加 (3-1)×count ,新字符串大小为,newSize = oldSize+2×count
- 两个指针从后开始遍历,
i=oldSize-1,j=newSize-1
,i是改变大小前字符所在原位置,j是改变大小后字符所在的新位置 - 如果i位置不是空格,就把该位置的字符放到j位置;如果i位置的字符是空格,就从j、j-1、j-2三个位置分别插入0、2、%,此时j需要往前走两步,才可以和i同步,否则会错位。
三、151.翻转字符串里的单词
思路:
1、删除多余的空格
2、反转整个字符串
3、反转单词
1、删除多余的空格
可以参考LeetCode 27.移除元素的思路,就是找到空格进行删除,再单词前移并补充空格
//1、删除多余的空格
void removeExtraSpace(string& s)
{
int slow = 0;//用来控制在单词后添加空格
for(int i=0;i<s.size();i++)
{
if(s[i]!=' ')//不是空格就处理 删除所有空格
{
if(slow!=0) s[slow++] = ' ';//给单词之间加空格
while(i<s.size() && s[i]!=' ')
{
s[slow++]=s[i++];//把整个单词前移
}
}
}
s.resize(slow);//slow的大小即为去除多余空格后的大小。
}
解释:
slow——用来控制在单词后添加空格,同时也记录了处理后字符串的长度,慢指针
i——这里相当于快指针
s[slow++]=s[i];——先赋值,slow再偏移
如果是i++ 最后一个单词没有反转
代码说明:
- 首先,从字符串头部开始遍历,如果不是空格就开始处理,也就是删除空格:
- 然后,判断此时慢指针所指的位置是不是第一个单词,如果不是第一个单词就添加空格,相当于此时已经把第一个单词已经整体向前移动了,需要在slow的下一个位置,即slow++的位置添加一个空格。
- 接着,继续通过slow来把下一个单词往前移动
- 最后,更新一下删除多余空格的字符串大小
2、反转整个字符串
可以参考LeetCode 344.反转字符串,可以自己写swap实现体,也可以调用swap函数,还可以调用reverse。上面的544也提到,不赘诉
//2、反转整个字符串
void reverseStr(string& s, int start, int end)
{
for(int i=start,j=end;i<j;i++, j--)
{
swap(s[i], s[j]);
}
}
3、反转单词
//3、反转单词
string reverseWords(string s)
{
removeExtraSpace(s);
reverseStr(s, 0, s.size()-1);
int start=0;
for(int i=0;i<=s.size();i++)//要取等号
{
if(s[i]==' ' || i==s.size())
{
reverseStr(s,start,i-1);
start=i+1;
}
}
return s;
}
方法: 每找到一个单词就反转这个单词,可以调用reverse
要求: 用reverse的话,需要找到字符串的起始位置,即反转的长度
代码思路
- 从头开始遍历s,用一个变量start来表示开始的位置,即
int start=0;
。removeExtraSpaces,删除了多余的空格后,字符串s第一个单词的开始下标一定是0。 - for循环找空格并反转单词,当
s[i]==' ';
时,表示找到了一个空格的位置,那么就反转这一小段的字符串。那么反转的的长度就是start~i-1这个范围 - 继续寻找下一个单词的长度,那么start要更新为第一个空格的下一个位置,也就是第二个单词开始的位置,然后再重复以上过程。
注意:
for循环如果不取等号i<s.size()
,并且i==s.size()-1
,最后一个单词的首字母没有反转,即het
for循环如果不取等号i<s.size()
,并且i==s.size()
,最后一个单词没有反转,即eht
for循环如果取等号i<=s.size()
,但i==s.size()-1
,最后一个单词的首字母没有反转,即het