今日任务
- 344.反转字符串
- 541. 反转字符串II
- 剑指Offer 05.替换空格
- 151.翻转字符串里的单词
- 剑指Offer58-II.左旋转字符串
一、反转字符串
难点在于不能给数组分配额外的空间
class Solution {
public:
void reverseString(vector<char>& s) {
for(int i =0,j=s.size()-1;i<s.size()/2;i++,j--){
swap(s[i],s[j]);
}
return;
}
};
字符转也算是比较熟悉的内容了,一遍过。
题解:
二、反转字符串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;
}
};
一开始思路不是很对,写了很多,照着题解把第二种情况融合到了第一种情况里面。
三、替换空格
题目解读:这道题如果不用额外空间的话就难一点。但基本方法是可以确定地——双指针法。
class Solution {
public:
string replaceSpace(string s) {
int old = s.size();
int num = 0;
for(int i=0;i<old;i++){
if(s[i]==' '){
num++;
}
}
s.resize(s.size()+2*num);
int new1 = s.size();
for(int i = new1-1,j=old-1;j<i;i--,j--){
if(s[j]!=' '){
s[i]=s[j];
}
else{
s[i] ='0';
s[i-1] = '2';
s[i-2] = '%';
i -=2;
}
}
return s;
}
};
基本算是一遍过,但是后面填数的时候忘了加单引号,找错误还是找的蛮久的。
四、翻转字符串里的单词
题目解读:在题解里提高了本题的难度,要求不使用辅助空间且空间复杂度要求位O(1)。
class Solution {
public:
void chuk(string& s){
int num = 0;
for(int i = 0;i<s.size();i++ ){
if(s[i] != ' '){
if(num!=0){
s[num++]=' ';
}
while(i<s.size()&&s[i]!=' '){
s[num++]=s[i++];
}
}
}
s.resize(num);
}
void reversed(string& s,int begin,int end){
for(int i=begin,j=end;i<j;i++,j--){
swap(s[i],s[j]);
}
}
string reverseWords(string s) {
chuk(s);
reversed(s,0,s.size()-1);
int j =0;
for(int i =0;i<=s.size();i++){
if(i==s.size()||s[i]==' ')
{
reversed(s,j,i-1);
j=i+1;
}
}
return s;
}
};
有两个地方比较难以理解,首先是在removeExtraSpace也就是移除空格的时候,题解里德算法将buslow非零的情况拿出来,在这种情况下是要接一个空格然后接单词的,所以有
if (slow != 0) s[slow++] = ' '
后面把头部和其他的地方算作一种。
另一个地方是在下面的主函数里面,在一个for循环中,i等于了s.size(),一般情况下,这是不允许的(因为可能造成溢出)。但在这里,为了不让句子末尾的单词需要单拎出来使用参数有变化的reverse函数,在这个值上,下面的if用或运算避免了这种情况,因为if判断语句中,如果前面的运算可以确定此次判断的值(此处i==s.size()时直接为true进入if下面的语句中),是不会再向后进行运算,直接执行或跳过。此处题解利用了这一点,避免了溢出 。
五、左旋字符串
题目解读:此题本身还是比较简单的,但是在题解中提升了本题的难度——不能申请额外的空间,只能在串上操作。
这样的话想要达到此题的目的还是比较难的。
题解中提出了这样的解法:1、反转区间为前n的子串
2、反转区间为n到末尾的子串
3、反转整个字符串
class Solution {
public:
string reverseLeftWords(string s, int n) {
reverse(s.begin(),s.begin()+n);
reverse(s.begin()+n,s.end());
reverse(s.begin(),s.end());
return s;
}
};
一开始思路错了,以为还得用到swap,没想到3个reverse直接结束。
不过在题解中发现一个比较有趣的解法。
class Solution {
public:
string reverseLeftWords(string s, int n) {
int len =s.size();
s.resize(len+n);
for(int i=0;i<n;i++){
s[len++] =s[i];
}
s.erase(0,n);
return s;
}
};
虽然用了额外空间了,但是这涉及到字符串轮转。
用了一个半点吧