Day08_字符串
1. 反转字符串
344. 反转字符串
思路:
首位交换
class Solution {
public:
void reverseString(vector<char>& s) {
int s_len= s.size();
int left = 0, right = s_len - 1;
while (left < right) {
swap(s[left++], s[right--]);
}
return ;
}
};
2. 反转字符串 II
541. 反转字符串 II
思路:
字符串反转的区间是
[i * 2 * k, i * 2 * k + k)
,遍历所有的反转区间,将字母首尾反转即可。
class Solution {
public:
string reverseStr(string s, int k) {
int s_len = s.length();
for (int i = 0; i*2*k < s_len; i++) {
int left = i * 2 * k;
int right = left + k - 1;
if (right >= s_len) right = s_len - 1;
while (left < right) {
char temp = s[left];
s[left++] = s[right];
s[right--] = temp;
}
}
return s;
}
};
3. 替换空格
方法一:
空间换时间,再开一个额外的字符串空间,存放答案。
class Solution {
public:
string replaceSpace(string s) {
int s_len = s.length();
string ans = "";
for (int i = 0; i < s_len; ++i) {
if (s[i] != ' ') ans += s[i];
else ans += "%20";
}
return ans;
}
};
方法二:
不开额外空间,提前算好替换后需要的总的数组空间大小,将字符串数组扩充。
从扩充后的数组尾部开始,利用双指针,从右向左遍历字符串,将字符依次移动到扩充后空间的相应位置。
这样的时间复杂度为 O ( n ) O(n) O(n)
如果从左向右遍历,每次需要将后面的所有字符向右移动,时间复杂度为 O ( n 2 ) O(n^2) O(n2)
class Solution {
public:
string replaceSpace(string s) {
int s_len = s.length();
int space_cnt = 0;
for (int i = 0; i < s_len; ++i) { // 统计空格的数量
if (s[i] == ' ') space_cnt++;
}
int new_len = s_len + space_cnt * 2;
s.resize(new_len); // 扩展字符串空间
for (int i = s_len - 1, j = new_len - 1; i < j; i--, j--) {
if (s[i] == ' ') {
s[j--] = '0';
s[j--] = '2';
s[j] = '%';
} else s[j] = s[i];
}
return s;
}
};
4. 反转字符串中的单词
151. 反转字符串中的单词
思路:
如果使用单词数组的话将变得很简单,只需要首尾交换单词即可,但是空间复杂度为 O ( n ) O(n) O(n)
如果要空间复杂度为 O ( 1 ) O(1) O(1),就不能另开一个数组
- 将整个字符串反转
- 然后去除开头,中间,结尾多余的空格
- 将每个单词反转回来
class Solution {
public:
void my_remove_extra_space(string &s) { // 去除字符串中多余的空格
int s_len = s.length();
int slow_index = 0;
for (int fast_index = 0; fast_index < s_len; ++fast_index) {
if (s[fast_index] != ' ') {
if (slow_index != 0) s[slow_index++] = ' '; // 单词之间添加空格
while (s[fast_index] != ' ' && fast_index < s_len) s[slow_index++] = s[fast_index++];
}
}
s.resize(slow_index);
}
void my_reverse(string &s, int left, int right) { // 将字符串left到right的部分反转
char temp;
while (left < right) {
temp = s[left];
s[left++] = s[right];
s[right--] = temp;
}
}
string reverseWords(string s) {
my_remove_extra_space(s);
int s_len = s.length();
my_reverse(s, 0, s_len - 1);
int left = 0, right;
for (int i = 0; i <= s_len; ++i) {
if (i == s_len || s[i] == ' ') {
right = i - 1;
my_reverse(s, left, right); // 把每个单词反转回来
left = i + 1;
}
}
return s;
}
};
5. 左旋转字符串
如果整体移动的话空间复杂度为 O ( n 2 ) O(n^2) O(n2)
这里用一个 O ( n ) O(n) O(n)的方法,原地左旋字符串
- 将[0, k)的字符串反转
- 将[k, s_len)的字符串反转
- 将整个字符串反转回来
太妙了!佩服佩服
class Solution {
public:
void my_reverse(string &s, int left, int right) {
while (left < right) {
swap(s[left++], s[right--]);
}
}
string reverseLeftWords(string s, int n) {
int s_len = s.length();
my_reverse(s, 0, n - 1);
my_reverse(s, n, s_len - 1);
my_reverse(s, 0, s_len - 1);
return s;
}
};