Leetcode刷题笔记Day4:字符串

71 阅读3分钟

反转字符串 II

  • 普通的反转就用双指针实现就好,来看些花式反转!
  • 力扣题目链接
  • 解法:
string reverseStr(string s, int k) {
    for(int i=0; i<s.size(); i+=2*k)
        if(i+k<=s.size())                   //判断是否不足k个字符
            reverse(s.begin()+i, s.begin()+i+k);
        else
            reverse(s.begin()+i, s.end());  //全部反转
    return s;
}
  • 算法复杂度:时间复杂度O(n),空间复杂度O(1)

翻转字符串里的单词

  • 最暴力的解法就是把单词一个个分离出来放到vector中,最后重组一个字符串
  • 一种比较好的思路是去除字符串前后的空白,然后反转,然后挨个单词反转
  • 力扣题目链接
  • 解法1:
string reverseWords(string s) {
    vector<string> words;
    for(int i=0; i<s.size(); i++){
        while(i<s.size() && s[i]==' ') i++;
        string t="";
        while(i<s.size() && s[i]!=' ') {t+=s[i]; i++;}
        if(t!="") words.push_back(t);
    }
    string t="";
    for(int i=words.size()-1; i>0; i--){
        t+=words[i];
        t+=" ";
    }
    t+=words[0];
    return t;
}
  • 解法2:
void reverse(string& s,int start,int end){
    for(int i=start, j=end; i<j; i++, j--) swap(s[i], s[j]);
}
void removeExtraSpace(string& s){
    int slow=0;
    for(int i=0; i<s.size(); i++)
        if(s[i]!=' '){
            if(slow!=0) s[slow++]=' ';
            while(i<s.size() && s[i]!=' ') s[slow++]=s[i++];
        }
    s.resize(slow); //slow的大小即为去除多余空格后的大小
}
string reverseWords(string s) {
    removeExtraSpace(s);
    reverse(s,0,s.size()-1);
    int start=0;
    for(int i=0;i<=s.size();i++)
        if(i==s.size() || s[i]==' '){
            reverse(s,start,i-1);
            start=i+1;
        }
    return s;
}
  • 算法复杂度:时间复杂度O(n),空间复杂度O(1)

右旋字符串

#include<iostream>
using namespace std;
void reverse(string& s, int start, int end){
    for(int i=start, j=end; i<j; i++, j--) swap(s[i],s[j]);
}
int main(){
    string s; int k;
    cin >> k >> s;
    reverse(s, 0, s.size()-1);
    reverse(s, 0, k-1);
    reverse(s, k, s.size()-1);
    cout << s;
}
  • 算法复杂度:时间复杂度O(n),空间复杂度O(1)

实现 strStr()

  • 搞清楚KMP算法,前缀表(PMT表)以及next数组的关系
  • 力扣题目链接
  • 解法1(PMT表):
int strStr(string haystack, string needle) {
    int n=haystack.size(), m=needle.size();
    vector<int> pi(m);          //PMT表
    for(int i=1, j=0; i<m; i++){
        while(j>0 && needle[i]!=needle[j]) j=pi[j-1];
        if(needle[i]==needle[j]) j++;
        pi[i]=j;
    }
    for(int i=0, j=0; i<n; i++){
        //失配
        while(j>0 && haystack[i]!=needle[j]) j=pi[j-1];
        if(haystack[i]==needle[j]) j++;
        if(j==m) return i-m+1;  //匹配成功
    }
    return -1;
}
  • 解法2(next数组):
void getNext(string needle, vector<int>& next){
    int i=0, j=-1; next[0]=j;
    while(i<needle.size()-1)
        if(j==-1 || needle[i]==needle[j]){
            i++; j++;
            next[i]=j;
        } else j=next[j];
}
int strStr(string haystack, string needle) {
    int n=haystack.size(), m=needle.size();
    vector<int> next(m);    //next数组
    getNext(needle, next);
    int i=0, j=0;
    while(i<n && j<m)
        if(j==-1 || haystack[i]==needle[j]) {i++; j++;}
        else j=next[j];
    if(j==m) return i-j;
    else return -1;
}
  • 算法复杂度:时间复杂度O(n),空间复杂度O(m)

重复的子字符串

bool repeatedSubstringPattern(string s) {
    string t=s+s;
    t.erase(t.begin()); t.erase(t.end()-1); //掐头去尾
    if(t.find(s)!=string::npos) return true;
    return false;
}

bool repeatedSubstringPattern(string s) {
    return (s + s).find(s, 1) != s.size();  //相当于string::pos
}
  • 解法2:
void getNext(vector<int>& next, string s){
    int j=0; next[0]=0;
    for(int i=1; i<s.size(); i++){
        while(j>0 && s[i]!=s[j]) j=next[j-1];
        if(s[i]==s[j]) j++;
        next[i]=j;
    }
}
bool repeatedSubstringPattern(string s) {
    int n=s.size();
    vector<int> next(n);
    getNext(next, s);
    if(next[n-1]!=0 && n%(n-next[n-1])==0) return true; //整除
    else return false;
}
  • 算法复杂度:时间复杂度O(n),空间复杂度O(n)

参考资料

[1] 代码随想录

[2] Leetcode题解