151. 反转字符串中的单词
给你一个字符串 s ,请你反转字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
题目链接:LeetCode151.反转字符串中的单词
文档讲解:代码随想录151.反转字符串中的单词
题解
移除空格、反转字符串、反转每个单词
class Solution {
public:
void removeSpaces(string& s) {
int j = 0;
for (int i = 0; i < s.size(); ++i) {
if (s[i] != ' ') {
if (j != 0) {
s[j++] = ' ';
}
while (i < s.size() && s[i] != ' ') {
s[j++] = s[i++];
}
}
}
s.resize(j);
}
void reverseString(string& s, int start, int end) {
for (int i = start, j = end; i < j; i++, j--) {
swap(s[i], s[j]);
}
}
string reverseWords(string s) {
removeSpaces(s);
reverseString(s, 0, s.size() - 1);
int start = 0;
for (int i = 0; i <= s.size(); ++i) {
if (s[i] == ' ' || i == s.size()) {
reverseString(s, start, i - 1);
start = i + 1;
}
}
return s;
}
};
- 时间复杂度:O(n)
- 空间复杂度:O(n)
卡码网55. 右旋字符串
题目描述
字符串的右旋转操作是把字符串尾部的若干个字符转移到字符串的前面。给定一个字符串 s 和一个正整数 k,请编写一个函数,将字符串中的后面 k 个字符移到字符串的前面,实现字符串的右旋转操作。
例如,对于输入字符串 “abcdefg” 和整数 2,函数应该将其转换为 “fgabcde”。
输入描述
输入共包含两行,第一行为一个正整数 k,代表右旋转的位数。第二行为字符串 s,代表需要旋转的字符串。
输出描述
输出共一行,为进行了右旋转操作后的字符串。
输入示例
2
abcdefg
输出示例
fgabcde
题目链接:卡码网55.右旋字符串
文档讲解:卡码网55.右旋字符串
题解
字符串分段、整体反转、分段反转
#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;
}
- 时间复杂度:O(n)
- 空间复杂度:O(1)
28. 找出字符串中第一个匹配项的下标
给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。
题解
KMP:构造next数组、利用next数组匹配
class Solution {
public:
void getNext(int* next, const string s) {
int j = -1;
next[0] = j;
for (int i = 1; i < s.size(); i++) {
while (j >= 0 && s[j + 1] != s[i]) {
j = next[j];
}
if (s[j + 1] == s[i]) {
j++;
}
next[i] = j;
}
}
int strStr(string haystack, string needle) {
if (needle.size() == 0) {
return 0;
}
int next[needle.size()];
getNext(&next[0], needle);
int j = -1;
for (int i = 0; i < haystack.size(); i++) {
while (j >= 0 && haystack[i] != needle[j + 1]) {
j = next[j];
}
if (haystack[i] == needle[j + 1]) {
j++;
}
if (j == (needle.size() - 1)) {
return (i - needle.size() + 1);
}
}
return -1;
}
};
- 时间复杂度:O(n+m)
- 空间复杂度:O(m)
459. 重复的子字符串
给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。
题目链接:LeetCode459.重复的子字符串
文档讲解:代码随想录459.重复的子字符串
题解
若存在重复子字符串,则字符串s+s中间位置存在s本身
class Solution {
public:
bool repeatedSubstringPattern(string s) {
string t = s + s;
t.erase(t.end() - 1);
if (t.find(s, 1) != std::string::npos) {
return true;
}
return false;
}
};
- 时间复杂度:O(n)
- 空间复杂度:O(1)
KMP:最小重复子字符串<-最长相等前后缀<-前缀表<-next数组
class Solution {
public:
void getNext(int* next, const string& s) {
int j = -1;
next[0] = j;
for (int i = 1; i < s.size(); i++) {
while (j >= 0 && s[j + 1] != s[i]) {
j = next[j];
}
if (s[j + 1] == s[i]) {
j++;
}
next[i] = j;
}
}
bool repeatedSubstringPattern(string s) {
if (s.size() == 0) {
return false;
}
int next[s.size()];
getNext(&next[0], s);
int len = s.size();
if (next[len - 1] != -1 && !(len % (len - next[len - 1] - 1))) {
return true;
}
return false;
}
};
- 时间复杂度:O(n)
- 空间复杂度:O(n)