代码随想录算法训练营:9/60

非科班学习算法day9 | LeetCode151:反转字符串中的单词 ,卡码.右旋字符串,Leetcode28:实现strStr() 

目录

介绍

一、基础概念补充:

1.  erase函数

2.KMP算法

二、LeetCode题目

1.LeetCode151: 反转字符串中的单词 

题目解析

 2.卡码.右旋字符串

题目解析

3.Leetcode28:实现strStr

题目解析

 

总结


介绍

包含LC的三道题目,还有相应概念的补充。

相关图解和更多版本:

代码随想录 (programmercarl.com)https://programmercarl.com/#%E6%9C%AC%E7%AB%99%E8%83%8C%E6%99%AF


一、基础概念补充:

1.  erase函数

C++中erase的用法_c++ erase-优快云博客

2.KMP算法

        代码随想录 (programmercarl.com)

帮你把KMP算法学个通透!B站(理论篇)

除了以上两个连接,还有大话数据结构相应部分可以阅读    

二、LeetCode题目

1.LeetCode151: 反转字符串中的单词 

题目链接:151. 反转字符串中的单词 - 力扣(LeetCode)

题目解析

       分为两个步骤,首先新建一个函数用来移除多余空格;之后反转整个字符串,最后按照每个单词去反转。返回字符串s。(我写了一个我便于理解的版本 0v0)

 c++代码如下:

class Solution {
public:
    void deletekongge(string& s) {
        // 删除多余空格
        for (int i = s.size() - 1; i > 0; i--) {
            // 删除多余空格
            if (s[i] == ' ' && s[i - 1] == s[i]) {
                s.erase(s.begin() + i);
            }
        }
        // 删除头部空格
        if (s.size() > 0 && s[0] == ' ') {
            s.erase(s.begin());
        }

        if (s.size() > 0 && s[s.size() - 1] == ' ') {
            s.erase(s.begin() + s.size() - 1);
        }
    }

    string reverseWords(string s) {
        deletekongge(s);
        reverse(s.begin(), s.end());
        int strat = 0;
        for (int i = 0; i <= s.size(); ++i) {
            if (s[i] == ' ' || i == s.size()) {
                reverse(s.begin() + strat, s.begin() + i);
                strat = i + 1;
            }
        }
        return s;
    }
};

注意点1:关于删除多余空格。我尝试过从前向后删除,但是会存在一个问题,就是删除一个元素,会导致后面元素的索引发生变化,而从后向前检索就不会存在这种状况。

注意点2:循环中负责的是:遇到两个重复的空格就进行删除操作。所以最后有可能会剩下开头和结尾的两个空格没有操作,所以要单独操作。

注意点3:最后的字符串内的单词有两种情况需要反转,一个是遇到空格,另一个是遍历结束,遇到空格,这里直接使用了reverse函数,所以遍历条件要更改为:i <= s.size()

注意点4:reverse函数内部的参数是引用形式,包括自己构建函数也要特别注意是不是需要引用形式传入。

 2.卡码.右旋字符串

题目链接:55. 右旋字符串(第八期模拟笔试) (kamacoder.com)

题目解析

       第一种思路就是先反转整个字符串,然后根据要求的长度,分别反转前后两部分字符串范围,直接返回;思路二是新建一个空间,使用append函数对字符串进行重新读取拼接。

 思路一C++代码如下: 

#include<iostream>
using namespace std;
#include<algorithm>
 
int main()
{
    string s;
    int k;
    cin >> k;
    cin >> s;
     
    int len = s.size();
     
    reverse(s.begin(), s.end());
    reverse(s.begin(), s.begin() + k);
    reverse(s.begin() + k , s.end());
     
    cout << s << endl;
}
 
 
/**************************************************************
    Problem: 1065
    User: odCYZ6r27J3eZLOmW5Y2bc2N83vw [kamaCoder74837]
    Language: C++
    Result: 正确
    Time:28 ms
    Memory:2180 kb
****************************************************************/

  思路二 c++代码如下:

#include<iostream>
using namespace std;
#include<algorithm>
 
int main()
{
    string s;
    int k;
     
    cin >> k;
    cin >> s;
     
    int len = s.size();
     
    string new_str = "";
    for(int i = len - k; i < len; i++)
    {
        new_str.append(1,s[i]);
    }
    for(int i = 0; i < len - k; i++)
    {
        new_str.append(1,s[i]);
    }
     
    cout << new_str << endl;
    return 0;
}
 
/**************************************************************
    Problem: 1065
    User: odCYZ6r27J3eZLOmW5Y2bc2N83vw [kamaCoder74837]
    Language: C++
    Result: 正确
    Time:30 ms
    Memory:2180 kb
****************************************************************/

3.Leetcode28:实现strStr

题目链接:28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)

题目解析

       KMP算法的实现(我看了一下午),以下采用next数组减一写法。

C++代码如下:

class Solution {
public:
    // 构建next数组
    void getnext(int* next, const string& s) {
        // 初始化.小技巧:j表示索引,也表示当前位置最长相等前后缀的长度
        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]) {
                // 向后移动i和j继续检查,但是i在外层循环已经定义了
                j++;
            }
            next[i] = j;
        }
    }

    // strStr
    int strStr(string haystack, string needle) {
        // 创建next数组
        vector<int> next(needle.size());

        // 获取str的next数组
        getnext(&next[0], needle);

        // 初始化
        int j = -1;

        // 根据next数组匹配两个字符串
        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++;
            }

            // 如果j遍历结束
            if (j == needle.size() - 1) {
                // 此时文本串指针位置包含整个模式串的长度
                return (i - needle.size() + 1);
            }
        }
        // 匹配失败
        return -1;
    }
};

注意点1:j的初始化为-1的目的是为了满足我们的-1的需求,同时真正对比开始为什么i从1是因为此时第一个[0]元素没有比较的价值,已经被初始化为-1,所以直接从下一位的后缀的末尾开始,那不就是[1]么。

 

总结


KMP算法感觉相当复杂,后面还需要深入学习;关于字符串部分,个人认为i很多特别底层或者增加代码的部分,没有必要,所以写了自己好理解的版本,打卡第9天,坚持!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值