151.翻转字符串里的单词
建议:这道题目基本把 刚刚做过的字符串操作 都覆盖了,不过就算知道解题思路,本题代码并不容易写,要多练一练。 题目链接/文章讲解/视频讲解
思路:
(1)移除多余空格
(2)将整个字符串反转
(3)将每个单词反转
class Solution {
public:
void reversestring(string s) {
int loop = s.size() / 2;
for (int i = 0, j = s.size() - 1; i < loop; i++, j--) {
swap(s[i], s[j]);
}
}
void removekong(string &s) {//用&才能修改源字符串
int n = s.size();
int slowIndex = 0;
for (int i = 0; i < s.size(); i++) {
if (s[i] != ' ') {//遇到非空格才处理
if (slowIndex != 0) { // 不等于0,说明跳过了前面的空格,从第一个单词开始
s[slowIndex++] = ' '; // 给第一个单词后面的补上空格
}
while (i < s.size() && s[i] != ' ') { // 补上该单词,遇到空格说明单词结束
s[slowIndex++] = s[i++];
}
}
}
//忘记重新给字符串大小赋值了
s.resize(slowIndex); //slow的大小即为去除多余空格后的大小。
}
string reverseWords(string s) {
// 1.去除多余空格
removekong(s);
// 2.翻转整个字符串
reverse(s.begin(), s.end());
// 3.翻转每个单词
int count = 0; // 记录每次翻转的单词组个数
int start = 0;//记录每次翻转的开始
for (int i = 0; i <= s.size(); i++) {
if (i<s.size() && s[i]!= ' ') {
count++;
} else {
reverse(s.begin() + start, s.begin() + start + count);
count = 0;
start = i+1;
}
}
return s;
}
};
其中翻转每个单词的时候,卡哥的代码更简洁:
for (int i = 0; i <= s.size(); ++i) {
if (i == s.size() || s[i] == ' ') { //到达空格或者串尾,说明一个单词结束。进行翻转。
reverse(s, start, i - 1); //翻转,注意是左闭右闭 []的翻转。
start = i + 1; //更新下一个单词的开始下标start
}
}
本题收获
1、split用法:C++中split的实现
2、erase删除元素用法,O(n)时间复杂度:earse用法
3、resize(重新设置):resize用法
卡码网:55.右旋转字符串
题目链接/文章讲解
自己思路:将需要转换的单词存在一个临时字符串中,然后在原有字符串基础上从后向前拼接:
#include <iostream>
#include <string>
using namespace std;
int main() {
int k;
string s;
cin>>k;
cin>>s;
// 创建一个临时字符串来保存被旋转的部分
string temp_s;
for (int i = int(s.size() - k); i < int(s.size()); ++i) {
temp_s.push_back(s[i]);
}
// 将字符串的前部分向后移动 k 个位置
for (int i = int(s.size() - 1); i >= k; --i) {
s[i] = s[i - k];
}
// 将临时字符串中的字符放到前面 k 个位置
for (int i = 0; i < k; ++i) {
s[i] = temp_s[i];
}
cout << s << endl;
return 0;
}
法1:辅助的两个字符串将源字符串拆开,最后拼接在一起
#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
using namespace std;
int main() {
int k;
string s;
cin >> k;
cin >> s;
//getline(cin, s);
string tmp1(k, '0');
string tmp2(s.size() - k, '0');
int count = k;
for (int i = 0, j = s.size() - 1; count > 0; count--)
{
tmp1[i++] = s[j--];
}
reverse(tmp1.begin(), tmp1.end());
for (int i = 0; i < s.size() - k; i++)
{
tmp2[i] = s[i];
}
string end_s = tmp1 + tmp2;
cout << end_s;
}
法2:卡哥思路:通过 整体倒叙,把两段子串顺序颠倒,两个段子串里的的字符在倒叙一把
#include<iostream>
#include<algorithm>
using namespace std;
int main() {
int n;
string s;
cin >> n;
cin >> s;
int len = s.size(); //获取长度
reverse(s.begin(), s.end()); // 整体反转
reverse(s.begin(), s.begin() + n); // 先反转前一段,长度n
reverse(s.begin() + n, s.end()); // 再反转后一段
cout << s << endl;
}
28. 实现 strStr() (本题可以跳过)
因为KMP算法很难,第一遍了解大概思路,二刷的时候,再看KMP会 好懂很多。题目链接/文章讲解/视频讲解
459.重复的子字符串 (本题可以跳过)
本题算是KMP算法的一个应用,不过 对KMP了解不够熟练的话,理解本题就难很多。 KMP和本题,一刷的时候 ,可以适当放过,了解怎么回事就行,二刷的时候再来硬啃。
题目链接/文章讲解/视频讲解
字符串总结 题目链接/文章讲解
有空自己总结:
双指针回顾 文章讲解
有空自己总结:
学习时间
2024.6.14