● 344.反转字符串
● 541. 反转字符串II
● 卡码网:54.替换数字
● 151.翻转字符串里的单词
● 卡码网:55.右旋转字符串
344.反转字符串
思路:简单题,双指针
收获:在做题时习惯手撸,基本上很少用库函数,对库函数的了解程度也逐渐下滑,经常忘记可以用库函数,这也不好,该用库函数还是要用,可以方便很多
void reverseString(vector<char>& s) {
int left = 0, right = s.size()-1;
while(left <= right) {
// c = s[left];
// s[left++] = s[right];
// s[right--] = c;
swap(s[left++], s[right--]);
}
return;
}
时间复杂度: O(n)
空间复杂度: O(1)
541.反转字符串II
思路:写了一堆判断代码,最后没想到只需要i+2k就可以成功解决。
多看,多学,菜就多练
string reverseStr(string s, int k) {
int len = s.size();
int right = k;
if(right < len) right = len;
for(int i = 0; i < len; i += 2 * k) {
int left = i;
right = i + k > len ? len : i + k;
while(left < right) {
swap(s[left++], s[--right]);
}
}
return s;
}
时间复杂度: O(n)
空间复杂度: O(1)
2.
class Solution {
public:
string reverseStr(string s, int k) {
for (int i = 0; i < s.size(); i = 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;
}
};
54.替换数字
思路:res += number;
int main(){
string s, res;
cin >> s;
for(int i = 0; i < s.size(); i++) {
if(s[i] >= 'a' && s[i] <= 'z') {
res += s[i];
} else {
res += "number";
}
}
cout << res;
return 0;
}
再想想。。。原地修改数组?可是替换一个数字就要往后挪呀,怎么搞,感觉这个已经是最优解了,时间复杂度很低了。
int main(){
string s;
cin >> s;
int count = 0;
for(int i = 0; i < s.size(); i++) {
if(s[i] >= '0' && s[i] <= '9')
++count;
}
s.resize(s.size() + count * 5);
int right = s.size() - 1;
for(int i = s.size() -1 - 5 * count; i >= 0; i--) {
if(s[i] >= '0' && s[i] <= '9') {
s[right--] = 'r';
s[right--] = 'e';
s[right--] = 'b';
s[right--] = 'm';
s[right--] = 'u';
s[right--] = 'n';
} else
s[right--] = s[i];
}
cout << s;
return 0;
}
时间复杂度:O(n)
空间复杂度:O(1)
好好好,先改变大小,从后向前赋值。想到了从后往前赋值,愣是没想到改变大小,因为我理解改变大小就得先遍历一次字符串,时间复杂度不是又上来了?为什么第二个实际运行还比第一个速度快呢?
151.翻转字符串里的单词
思路1:先反转子字符串,再反转整个字符串。有额外空间
string reverseWords(string s) {
string res = "";
int right = 0;
cout << s.size() << endl;
while(right < s.size()) {
string ss = "";
while(s[right] == ' ') {
right++;
}
while(right < s.size() && s[right] != ' ') {
ss += s[right++];
}
reverse(ss.begin(), ss.end());
right++;
res += ss;
while(right < s.size() && s[right] == ' ') {
right++;
}
cout << right << endl;
if (right < s.size())
res += ' ';
}
reverse(res.begin(), res.end());
return res;
}
2.思路:原地修改数组,找到单词组,反转后提至字符串头(总体思路和删除元素一样)。然后找到空格数,resize下。
void reverseWord(string& s, int begin, int end, int left, int right){
while(begin <= end && end < s.size()) {
if (right < s.size() && left <= right) {
swap(s[left], s[right--]);
}
s[begin++] = s[left++];
}
return;
}
string reverseWords(string s) {
int right = 0, left = 0;
int res = 0;
int num = 0; // 空格数
int end = 0;
while(left < s.size() && right < s.size()) {
while(s[left] == ' ') {
left++;
num++;
}
if(left == s.size() && s[right] == ' ')
num++;
right = left;
while(right < s.size() && s[right] != ' ') {
right++;
}
end = res + right - left;
reverseWord(s, res, end - 1, left, right-1);
s[end] = ' ';
left = ++right;
if(left == s.size() && s[right-1] == ' ')
num++;
res = end + 1;
}
s.resize(s.size()-num);
reverse(s.begin(), s.end());
return s;
}
55.右旋转字符串
思路: 反转两个字串,再反转整串。
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
string s;
int k;
cin >> k >> s;
reverse(s.end() - k, s.end());
reverse(s.begin(), s.end() - k);
reverse(s.begin(), s.end());
// reverse(s.begin(), s.end()); // 整体反转
// reverse(s.begin(), s.begin() + k); // 先反转前一段,长度n
// reverse(s.begin() + k, s.end()); // 再反转后一段
cout << s << endl;
return 0;
}