代码随想录算法训练营第8天| ● 344.反转字符串 ● 541. 反转字符串II ● 剑指Offer 05.替换空格 ● 151.翻转字符串里的单词 ● 剑指Offer58-II.左旋转字符串
344.反转字符串
mydemo--(一次就过)--(成功)
class Solution {
public:
void reverseString(vector<char>& s) {
int len = s.size();
char tmp;
int i=0;
int j = len-1;
while(i<j)
{
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
i++;
j--;
}
}
};
卡哥代码
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]);
}
};
541.反转字符串Ⅱ
mydemo--(自己思路)--(失败)
报错:超出时间限制
判断写的太复杂,而且 i是一个一个的跳,太慢了,会超时。
class Solution {
public:
string reverseStr(string s, int k) {
int i = 0;
int j = 1;
int len = s.size();
while(1)
{
if(j-i+1 == 2*k)
{
reverse(s, i, i+k-1);
if(j == len-1) break;
i = j+1;
j = i+1;
continue;
}
if(j-i+1 < k && j ==len-1)
{
reverse(s,i,j);
break;
}
if(j-i+1 <2*k && j == len-1)
{
reverse(s,i,i+k-1);
break;
}
i++ //一个一个跳,太慢了
}
return s;
}
void reverse(string& s, int i, int j)
{
while(i < j)
{
swap(s[i], s[j]);
i++;
j--;
}
}
};
卡哥代码
卡哥真言:
当操作字符串或者操作数组的时候,如果需要成段成段的处理,那么 i 就可以成段成段的跳,速度会快很多。
class Solution {
public:
string reverseStr(string s, int k) {
int len = s.size();
for(int i=0; i<len; i+=2*k)
{
if(i+k <= len)
{
reverse(s.begin()+i, s.begin()+i+k); //库函数实现的reverse是左闭右开的
continue;
}
reverse(s.begin()+i, s.end());
}
return s;
}
};
剑指Offer 05.替换空格
mydemo--(自己思路)--(失败)
我的思路肯定是没问题的,只是写法上有瑕疵
注意
C++中单引号表示字符,双引号表示字符串
卡哥demo
又是一道双指针的题。
当对连续序列(数组、字符串)等进行删除,替换操作时,有前向法和后向法:
- 前向法:
在原序列上定义一个指针,当碰到要删除或者要替换的单位时,进行操作,同时,会对后面的单位进行处理,所以总的时间复杂度会是O(n^2)
- 后向法
在原序列上进行扩充,然后定义两个指针进行操作。这样做有两个好处:
- 不用申请新数组。
- 从后向前填充元素,避免了从前向后填充元素时,每次添加元素都要将添加元素之后的所有元素向后移动的问题。
class Solution {
public:
string replaceSpace(string s) {
int count = 0;
int sOldSize = s.size();
for(int i=0; i <s.size(); i++)
{
if(s[i] == ' ')
{
count++;
}
}
s.resize(s.size() + count*2); //key
int sNewSize = s.size();
for(int i = sNewSize - 1, j = sOldSize - 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;
}
};
151.反转字符串中的单词
卡哥demo
双指针法,原地修改
class Solution {
public:
void reverse(string& s, int start, int end)
{
for(int i = start, j = end; i < j; i++,j--)
swap(s[i], s[j]);
}
void removeExtraSpaces(string& s)
{
int slow = 0;
for(int fast = 0; fast < s.size(); fast++)
{
if(s[fast] != ' ')
{
if(slow !=0)
{
s[slow] = ' ';
slow++;
}
while(fast < s.size() && s[fast] != ' ')
{
s[slow] = s[fast];
slow++;
fast++;
}
}
}
s.resize(slow);
}
string reverseWords(string s)
{
removeExtraSpaces(s);
reverse(s, 0, s.size() - 1);
int start = 0;
for(int i = 0; i <= s.size(); i++)
{
if(i == s.size() || s[i] == ' ')
{
reverse(s, start, i-1);
start = i+1;
}
}
return s;
}
};
剑指Offer 58 - Ⅱ. 左旋转字符串
卡哥demo
注意,库函数的 reverse( ) 是左闭右开
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;
}
};