代码随想录
C/C++的字符串处理可以参考之前总结的两篇文章:C语言字符串的处理总结和C++字符串的处理总结
这个题是这几天来最简单的一个题了,没有难点,以中间为对称轴,两边交换即可。代码如下:
class Solution {
public:
void reverseString(vector<char>& s) {
int len = s.size();
int mid = len / 2;
for(int i=0;i<mid;i++)
{
char tmp = s[i];
s[i] = s[len-i-1];
s[len-i-1] = tmp;
}
}
};
这个题没必要使用C++里的reserve()函数,否则这个题就没有意义了。
这个题在上一个题的基础上稍微增加了一些难度,但整体也不难。以2k个字符为一组,前k个反转,后k个保持原来的顺序,以这样的方式进行循环,代码实现如下:
class Solution {
public:
string reverseStr(string s, int k) {
string res,sub;
int size = s.size();
int index = 0;
while(index < size)
{
sub = s.substr(index,k);
reverse(sub.begin(),sub.end());
res += sub;
index += k;
if(index < size) // 判断是否还有字符
{
sub = s.substr(index,k);
res += sub; //保持原来的顺序
index += k;
}
}
return res;
}
};
上一个题已经会怎么反转字符串了,所以这个题可以直接调用reserve()函数,另外还用了substr()函数,第一个参数是起始位置,第二个参数是长度,如果长度超过字符串的长度就忽略超出的部分,所以不需要担心越界。
如果不是用额外的空间,直接在原来的字符串上进行反转,代码如下:
class Solution {
public:
string reverseStr(string s, int k) {
for(int i=0;i<s.size();i += 2*k)
if(i + k < s.size()) //足够k个字符
reverse(s.begin()+i,s.begin()+i+k);
else //不足k个字符
reverse(s.begin()+i,s.end());
return s;
}
};
定义一个新的string变量来保存结果res,遍历字符串,如果是空格,则res += “%20”,否则将这个字符添加到res中,非常的简单。
class Solution {
public:
string replaceSpace(string s) {
string res;
for(int i=0;i<s.size();i++)
{
if(s[i] != ' ') res += s[i];
else res += "%20";
}
return res;
}
};
代码随想录中给出了不用额外申请空间(对原来的字符串进行扩容)的方法,但必须先遍历一遍数组,得到空格的出现的次数,然后再在原来空间的基础之上进行扩充,这样做的好处是节省空间,缺点是相对要多消耗一些时间,代码如下:
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的大小,也就是每个空格替换成"%20"之后的大小
s.resize(s.size() + count * 2);
int sNewSize = s.size();
// 从后先前将空格替换为"%20"
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;
}
};
先将字符串以空格进行分割,放入到vector中,然后从后往前重构字符串,每个子串后面要添加一个空格(最后一个子串除外),字符串的分割可参考C++字符串的处理总结中的字符分割。
class Solution {
public:
string reverseWords(string s) {
stringstream ss(s);
string str;
vector<string> vec;
//分割字符串
while(ss >> str) vec.push_back(str);
str = "";
//从后往前添加
for(int i=vec.size()-1;i>=0;i--)
{
str += vec[i];
str += " ";
}
str.erase(str.end()-1);
return str;
}
};
代码随想录里提供了另一解题思路,不使用额外的辅助空间,解题步骤如下:
class Solution {
public:
string reverseWords(string s) {
int i = 0, j = 0;
//去除开头的空格
while(i < s.size() && s[i] == ' ') i++;
//去除中间和末尾的字符
while(i < s.size())
{
if(s[i] != ' ') s[j++] = s[i++];
else
{
//去除空格
while(i < s.size() && s[i] == ' ') i++;
if(i < s.size()) s[j++] = ' '; //添加单词间的空格
}
}
s.resize(j); //重新指定大小
//反转这个字符串
reverse(s.begin(),s.end());
//反转每个单词
i = 0,j = 0;
while(i < s.size())
{
while(i < s.size() && s[i] != ' ') i++;
reverse(s.begin()+j,s.begin()+i);
j = ++i;
}
return s;
}
};
简单粗暴的调用函数:
class Solution {
public:
string reverseLeftWords(string s, int n) {
string str1 = s.substr(0,n);
string str2 = s.substr(n);
return str2+str1;
}
};
注意返回时是str2+str1
,和str1+str2
不一样!!!
代码随想录提供了另一种思路,同样不需要额外的辅助空间,思路如下:
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;
}
};
今天的题可以难也可以简单,如果都通过调函数来实现就很简单,如果要求空间复杂度为O(1),只能在原来的字符串上进行变换则就有一定的难度了。平时练习的时候注意多种方法的实现,特别是不使用额外的辅助空间,一方面能帮助真正掌握字符串的处理,另一方面也能够锻炼编程能力。