151.翻转字符串里的单词
给定一个字符串,逐个翻转字符串中的每个单词。
要求:不要使用辅助空间,空间复杂度要求为O(1)
如何去除多余的空隔?利用双指针。
class Solution {
public:
//用swap来构建自己的翻转函数
void reversemy(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) {
//去除多余的空隔
int slow = 0, fast = 0;
for(;fast<s.size();fast++){
if(s[fast]!=' '){
if (slow!= 0) s[slow++] = ' '; //如果slow不是第一个字符,则每次在fast碰到非字符时,slow加上一个空隔,用作每个字符串之间的间隔
while(fast<s.size()&&s[fast]!=' '){
s[slow++] = s[fast++];
}
}
}
s.resize(slow);
//翻转再翻转
int startidx = 0;
reversemy(s, 0, s.size()-1);
for(int i=0; i<=s.size(); i++){
if(i==s.size()||s[i]==' '){
reversemy(s,startidx,i-1);
startidx = i+1;
}
}
return s;
}
};
- 时间复杂度: O(n)
- 空间复杂度: O(1) 或 O(n),取决于语言中字符串是否可变
右旋字符串
字符串的右旋转操作是把字符串尾部的若干个字符转移到字符串的前面。给定一个字符串 s 和一个正整数 k,请编写一个函数,将字符串中的后面 k 个字符移到字符串的前面,实现字符串的右旋转操作。
对于输入字符串 "abcdefg" 和整数 2,函数应该将其转换为 "fgabcde"。
思路:
1. 字符串全部翻转;gfedcba
2. 对前k个数进行翻转;fgedcba
3. 对后str.size-k个数进行翻转;fgzbcd
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
void reversemy(string& s, int start, int end){
for(int i = start, j = end; i<j; i++, j--){
swap(s[i],s[j]);
}
}
int main(){
int k;
string str;
cin >> k;
cin >> str;
reversemy(str, 0, str.size()-1);
reversemy(str, 0, k-1);
reversemy(str, k, str.size()-1);
cout<<str<<endl;
}
- 时间复杂度: O(n)
- 空间复杂度: O(1)
28. 实现 strStr()
实现 strStr() 函数。
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。
KMP:
使用在字符串匹配的问题。
本题是KMP 经典题目。KMP的经典思想就是:当出现字符串不匹配时,可以记录一部分之前已经匹配的文本内容,利用这些信息避免从头再去做匹配。
文本串:aabaabaaf
模式串:aabaaf
a a b a a b a a f
a a b a a f
什么是前缀表?
next数组就是一个前缀表(prefix table)。能让我们去找到之前已经匹配过的内容。
前缀表:起始位置到下标i之前(包括i)的子串中,有多大长度的相同前缀后缀。
前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配的时候,模式串应该从哪里开始重新匹配。
循环不变量:遇到冲突看前一位
459.重复的子字符串
kmp有点难,之后再补