今日更新题目:344.反转字符串,541. 反转字符串II,54.替换数字
理论基础
对于C++中的string,只需要把它当作可动态调整大小的char数组即可,调用方法见 cppreference
344. 反转字符串
本题思路类似反转链表那题,甚至还更简单,因为链表反转需要改变指针方向,本题只需要使用双指针从两头开始,不断调换两边的值即可。本题较为简单,此处不做过多赘述
class Solution {
public:
void reverseString(vector<char>& s) {
// 还有一种循环结束条件是 i < s.size()/2
for (int i = 0, j = s.size() - 1; i < j; i++, j--) {
swap(s[i], s[j]);
}
}
};
541. 反转字符串II
我的错误理解:反转这 2k
字符中的前 k
个字符,后k个字符按照下面的情况二三反转,于是开始懵逼,后k个字符,就算足够,最大也不超过k个啊,怎么会有两种情况呢?然后重新看了代码随想录的视频讲解。果然,很多时候难的不是题目,是自己的理解有问题。
本题最重要的还是理解题中的反转规则,根据题意:
-
情况一:对于长度满足2k的字串,仅反转这 2k 个字符中的前 k 个字符
-
对于长度不满足2k的字串(即字符串末尾部分的处理)
- 情况二:若剩余字符少于 k 个,则将剩余字符全部反转
- 情况三:若剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样
写代码时会发现情况一和三是可以合并的,只要长度大于k,都是只反转前k个,余下的不变,因此可以合并
class Solution {
public:
string reverseStr(string s, int k) {
for(int i = 0; i < s.size(); i += (2 * k)){
// 对于长度满足2k的字串,仅反转这2k个字符中的前k个字符
// 若剩余字符<2k && >= k 个,则反转前k个字符,其余保持原样
if((s.size() - i) >= k){
// 反转当前位置开始的前k个字符
reverse(s.begin() + i, s.begin() + i + k);
}
else{
// 反转当前位置到最后位置的所有字符
reverse(s.begin() + i, s.end());
}
}
return s;
}
};
54.替换数字
本题我的最初想法是想一次遍历完成任务,但是发现必须先知道有多少个数字,才能确定新的字符串s扩容后的容量。因此思路变为:先遍历一遍字符串s,完成扩容步骤;再从后往前遍历并按照规则移动或者填充number即可
为什么不从前往后:模拟一遍即可知道,前面的字母根本无法确定最终位置,且可能覆盖了原来的值。
#include<iostream>
using namespace std;
int main(){
string s;
while(cin >> s){
int count = 0;
int size1 = s.size() - 1;
for(int i = 0; i < s.size(); i++){
if(s[i] >= '0' && s[i] <= '9')
count++;
}
s.resize(s.size() + count * 5);
for(int i = size1, j = s.size()-1; i >= 0; i--){
if(s[i] >= '0' && s[i] <= '9'){
s[j--] = 'r';
s[j--] = 'e';
s[j--] = 'b';
s[j--] = 'm';
s[j--] = 'u';
s[j--] = 'n';
}
else{
s[j--] = s[i];
}
}
cout << s << endl;
}
return 0;
}