1.反转字符串
题目链接/文章讲解/视频讲解: 代码随想录
代码:(双指针法)
class Solution {
public:
void reverseString(vector<char>& s) {
int left = 0;
int right = s.size() - 1;
int t = 0;
// 区间是左闭右闭
while(left <= right){
t = s[left];
s[left] = s[right];
s[right] = t;
left++;
right--;
}
}
};
思路:这题简单的。 但是我又脑抽写成了交换下标。。。。
2.反转字符串II
题目链接/文章讲解/视频讲解: 代码随想录
代码:
class Solution {
public:
string reverseStr(string s, int k) {
// 每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。
for(int i = 0;i < s.size(); i += 2*k){
// 如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
if(i + k <= s.size()){
reverse(s.begin() + i,s.begin() + i + k);
}else{
// 如果剩余字符少于 k 个,则将剩余字符全部反转。
reverse(s.begin() + i,s.end());
}
}
return s;
}
};
思路:每2k个字符长度要做一次处理,所以可以直接让遍历后的i += 2*k,for循环的技巧。
还有就是,这个条件判断写着有点别扭。判断是看i+k的大小的,循环就是看i+2k的大小了。
3.替换数字
题目链接/文章讲解: 代码随想录
代码:
# include <iostream>
using namespace std;
int main(){
string s;
while(cin >> s){
// 数组从前向后遍历会影响到后续元素的移动,因此我们从后向前遍历
// sOld是我们从后往前遍历原数组要用到的
int sOld = s.size() - 1;
int count = 0;
// 统计字符串里有多少数字,方便后续扩容
for(int i = 0;i < s.size();i++ ){
if(s[i] >= '0'&& s[i] <= '9'){
count++;
}
}
// 给字符串扩容,number比单个的数字多5个字节
s.resize(s.size() + count * 5);
// sNew是遍历新数组要用到的
int sNew = s.size() - 1;
for( ;sOld >= 0;sOld--){
if(s[sOld] >= '0'&&s[sOld] <='9'){
s[sNew--] = 'r';
s[sNew--] = 'e';
s[sNew--] = 'b';
s[sNew--] = 'm';
s[sNew--] = 'u';
s[sNew--] = 'n';
}else{
s[sNew--] = s[sOld];
}
}
cout << s << endl;
}
}
思路:从后向前遍历数组可以减少时间复杂度。自己不熟悉这种acm格式写题。
4.翻转字符串里的单词
题目链接/文章讲解/视频讲解: 代码随想录
代码:
class Solution {
public:
void removeExtraSpaces(string &s){
// 这里一定要注意判断条件是原字符串还是新字符串
int slow = 0;
for(int fast = 0;fast < s.size();fast++){
// fast去遍历原字符串,slow来填新字符串
// 我们是要去除多余的空格,所以要填到新字符串的元素不是空格
if(s[fast] != ' '){
// 在单词的开头,还是要填一个空格
if(slow != 0)
s[slow++] = ' ';
// 将原字符串的字母搬运到新字符串中
while(fast < s.size() && s[fast] != ' '){
s[slow++] = s[fast++];
}
}
}
s.resize(slow);
}
void reverse(string &s,int start,int end){
while(start < end){
int i = s[start];
s[start] = s[end];
s[end] = i;
start++;
end--;
}
}
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] == ' '){
//为了让结束位置也符合我们循环里的步骤,i要遍历到字符串外
reverse(s,start,i - 1); // s[i]是空格,我们翻转的是单词,所以传入s[i-1]
start = i + 1; // 空格的下一个元素就是下一个单词的开始位置
}
}
return s;
}
};
状态:我真的要被bug死了。。。
首先是分不清fast和slow,在条件判断的时候用哪个;其次是翻转的函数里,我又把值和小标弄混了;然后是在翻转单词的时候,弄错了传入函数的参数(s[i]是空格,我只需要把单词传进去);然后是搞混了最后寻找空格的遍历函数的边界条件。。。。。
4.右旋转字符串
题目链接/文章讲解:
代码:
#include<iostream>
#include<algorithm>
using namespace std;
int main() {
int n;
string s;
cin >> n;
cin >> s;
reverse(s.begin(),s.end());
reverse(s.begin(),s.begin() + n);
reverse(s.begin() + n,s.end());
cout << s << endl;
}
状态:
救命,一直写错单词,reverse,reverse,reverse,重要的单词打三遍。。。
题目的思路就是,局部旋转+整体旋转。局部怎么转,自己可以试着画图。只要是让指定的区间翻转就行了。