代码随想录打卡Day9

今天字符串的前两道还好,后两道直接跳过了。。感觉那个KMP算法太难了,我看了视频还是觉得云里雾里的。。
前两道题的思路都是整体反转+局部反转,我觉得这个套路很经典。

151.翻转字符串里的单词

这道题直接将所有字符串反转,然后删除多余的空格,最后将每一个单词反转即可,反转整个字符串和局部的单词可以使用reverse()函数,删除多余的空格还是用经典的双指针法来实现。
这是我的代码

class Solution {
public:
    string reverseWords(string s) {
        // 1. 先去除多余空格
        int i, j;
        i = 0;
        j = 0;
        while(j < s.size()){
            if(s[j] != ' '){
                if(i != 0){
                    s[i] = ' ';
                    i++;
                }
                while(j < s.size() && s[j] != ' '){
                    s[i] = s[j];
                    i++;
                    j++;
                }
            }
            j++;
        }
        s.resize(i);
        // 2. 反转字符串
        for(i = 0, j = s.size() - 1; i < j; ){
            char temp = s[i];
            s[i] = s[j];
            s[j] = temp;
            i++;
            j--;
        }
        // return s;
        // 3.反转字符串中的单词
        i = 0;
        j = 0;
        while(i < s.size()){
            while(s[i] != ' ' && i < s.size())  //找到下一个空格的位置
                i++;
            reverse(s.begin() + j, s.begin() + i);
            i++;
            j = i;
        }
        return s;
    }
};

卡码网:55.右旋转字符串

这个和上一题思路一样,我偷懒直接调用库函数了,很快就AC
这是我的代码

#include<string>
#include<iostream>
#include<algorithm>
using namespace std;

void my_rotate(string &s, int k){
    reverse(s.begin(), s.end());
    reverse(s.begin(), s.begin() + k);
    reverse(s.begin() + k, s.end());
}

int main(){
    int k;
    string s;
    cin >> k;
    cin >> s;
    my_rotate(s, k);
    cout << s << endl;
}

后面两道题居然是简单难度???!这两道题目的思路感觉都很难,看来还是要找时间把KMP算法啃一啃。。把那两道题弄明白以后我会更新这篇博客。我一定会回来的。


今天是8月23号,把KMP算法的流程弄懂了,但是我感觉还不够牢固,就只做了一题,还有一题留着明天做。

28. 实现 strStr()

这道题的难点在于两个:
1.如何构造next数组
2.有了next数组以后,应该如何去匹配。
首先构造next数组的方式是固定的,一般来说将其封装成一个函数会更加方便,至于构造next数组的具体实现流程,直接去代码随想录看讲解就可以。
但是代码随想录视频没有具体讲解你拿到next数组以后应该如何去匹配,简单来说就是用两个指针i和j,i指向haystack,j指向needle,使用一个循环,当i遍历完haystack中的所有字符后循环终止,在循环中则比较i和j指向的字符是否相等,若相等,则i和j都向后偏移一位,若不相等,则j跳转到next[j - 1]的位置,如果此时j已经为0,则j不再跳转,直接让i向后偏移一位。当找到匹配项时,此时j=needle.size(),直接return i - j即可,提前终止循环。
这是我的代码

class Solution {
public:
    int strStr(string haystack, string needle) {
        vector<int> next(needle.size());
        getNext(needle, next);
        int i, j;
        for(i = 0, j = 0; i < haystack.size(); ){
            if(haystack[i] == needle[j]){
                j++;
                i++;
                if(j >= needle.size())
                    return i - j;
            }  
            else{
                if(j > 0)
                    j = next[j - 1];
                else
                    i++;
            }
        }
        return -1;
    }
    void getNext(string s, vector<int> &next){
        /**************1.初始化**************/
        //i为后缀末尾位置,j为前缀末尾位置
        int i, j;
        j = 0;
        next[0] = 0;
        
        for(i = 1; i < s.size(); i++){
            /**************2.前后缀不相同**************/
            while(j > 0 && s[i] != s[j])
                j = next[j - 1];
            /**************3.前后缀相同***************/
            if(s[i] == s[j])
                j++;
            /**************4.更新next数组***************/
            next[i] = j;
        }
    }
};

今天是8月24号,把剩下的一题也做了,感觉在做的时候对next数组的构造流程还是有些生疏。
这道题目就直接对输入的字符串s求next数组,next数组最后一个位置存放的数就代表着字符串s的最长相等前后缀的长度,如果这个字符串可以由某个子串构成的话,则子串的长度就是s.size() - next[s.size() - 1],如果求得的子串长度为0,则说明不能由某个子串构成,这个判断逻辑不能少!!!如果不为0,则用s.size()对子串长度求余,若结果为0则说明可以构成,否则不可以
这是我的代码。

class Solution {
public:
    bool repeatedSubstringPattern(string s) {
        vector<int> next(s.size());
        getNext(next, s);
        //如果一个字符串可以由一个子串重复构成,则len(sub) == s.size() - next[s.size() - 1]
        if(next[s.size() - 1] != 0 && s.size() % (s.size() - next[s.size() - 1]) == 0)
            return true;
        return false;
    }
    void getNext(vector<int> &next, string s){
        //1.初始化
        int i, j;  //j指向前缀末尾,i指向后缀末尾
        j = 0;
        next[0] = 0;
        
        for(i = 1; i < s.size(); i++){
            //2.前后缀不相等
            while(j > 0 && s[i] != s[j])
                j = next[j - 1];
            //3.前后缀相等
            if(s[i] == s[j])
                j++;
            //4.更新next数组
            next[i] = j;
        }
    }
};

这几道题终于刷完了,感觉KMP算法还是有点难,后面肯定得二刷。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值