首页 > 编程语言 >代码随想录算法训练营day09|151.翻转字符串里的单词,卡码网:55.右旋转字符串,28.实现 strStr(),459.重复的子字符串

代码随想录算法训练营day09|151.翻转字符串里的单词,卡码网:55.右旋转字符串,28.实现 strStr(),459.重复的子字符串

时间:2024-08-17 14:04:45浏览次数:14  
标签:151 string int 随想录 next ++ && 字符串 size

151.翻转字符串里的单词

题目链接:https://leetcode.cn/problems/reverse-words-in-a-string/description/

暴力removeExtraSpaces:

void removeExtraSpaces(string& s) {
        for (int i = s.size() - 1; i > 0; i--) {
            if (s[i] == ' ' && s[i] == s[i - 1]) {
                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);
        }
    }

遇到多余空格就erase一下,时间复杂度比较高。

removeExtraSpaces版本一:

void removeExtraSpaces(string& s) {
        int slowIndex = 0, fastIndex = 0;
        while (s.size() > 0 && fastIndex < s.size() && s[fastIndex] == ' ') {
            fastIndex++;
        }
        for (; fastIndex < s.size(); fastIndex++) {
            if (fastIndex > 1 && s[fastIndex] == s[fastIndex - 1] &&
                s[fastIndex] == ' ') {
                continue;
            } else {
                s[slowIndex++] = s[fastIndex];
            }
        }
        if (slowIndex > 1 && s[slowIndex - 1] == ' ') {
            s.resize(slowIndex - 1);
        } else {
            s.resize(slowIndex);
        }
    }

一般的思考过程,就是先移除字符串前的空格,再移除中间的,再移除后面部分。

removeExtraSpaces版本二:

void removeExtraSpaces(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);
    }

比版本一精简,遇到非空格就处理。

完整代码:

class Solution {
public:
    void reverse(string& s, int start, int end) {
        for (int i = start, j = end; i < j; i++, j--) {
            swap(s[i], s[j]);
        }
    }
    void removeExtraSpaces(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);
    }
    string reverseWords(string s) {
        removeExtraSpaces(s);
        reverse(s, 0, s.size() - 1);
        int start = 0;
        for (int i = 0; i <= s.size(); ++i) {
            if (s[i] == ' ' || i == s.size()) {
                reverse(s, start, i - 1);
                start = i + 1;
            }
        }
        return s;
    }
};

比较综合的一道题目。

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

题目链接:https://kamacoder.com/problempage.php?pid=1065

我的代码:

#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 n;
    cin >> n >> s;
    reverse(s, 0, s.size() - 1);
    reverse(s, 0, n - 1);
    reverse(s, n, s.size() - 1);
    cout << s << endl;
    return 0;
}

通过三次倒序,一次整体倒序,两次分段倒序,得到右旋子串。

28.实现 strStr()

题目链接:https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/description/

前缀表(不减一)C++实现:

class Solution {
public:
    void getNext(int* next, const string& s) {
        int j = 0;
        next[0] = j;
        for (int i = 1; i < s.size(); i++) {
            while (j > 0 && s[j] != s[i]) {
                j = next[j - 1];
            }
            if (s[j] == s[i]) {
                j++;
            }
            next[i] = j;
        }
    }
    int strStr(string haystack, string needle) {
        vector<int> next(needle.size());
        getNext(&next[0], needle);
        int j = 0;
        for (int i = 0; i < haystack.size(); i++) {
            while (j > 0 && needle[j] != haystack[i]) {
                j = next[j - 1];
            }
            if (needle[j] == haystack[i]) {
                j++;
            }
            if (j == needle.size()) {
                return i - j + 1;
            }
        }
        return -1;
    }
};

直接用前缀表作为next数组的值,KMP算法的典型例题。

前缀表统一减一C++实现:

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) {
        vector<int> next(needle.size());
        getNext(&next[0], needle);
        int j = -1;
        for (int i = 0; i < haystack.size(); i++) {
            while (j >= 0 && needle[j + 1] != haystack[i]) {
                j = next[j];
            }
            if (needle[j + 1] == haystack[i]) {
                j++;
            }
            if (j == needle.size() - 1) {
                return i - j;
            }
        }
        return -1;
    }
};

前缀表减一作为next数组的值,KMP算法的典型例题。

459.重复的子字符串

题目链接:https://leetcode.cn/problems/repeated-substring-pattern/description/

移动匹配法:

class Solution {
public:
    bool repeatedSubstringPattern(string s) {
        string t = s + s;
        t.erase(t.begin());
        t.erase(t.end() - 1);
        if (t.find(s) != std::string::npos)
            return true;
        return false;
    }
};

判断字符串s是否由重复子串组成,只要两个s拼接在一起,里面还出现一个s的话,就说明是由重复子串组成,要注意刨除 s + s 的首字符和尾字符,这样避免在s+s中搜索出原来的s。

KMP(前缀表统一减一):

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) {
        vector<int> next(s.size());
        getNext(&next[0], s);
        int len = s.size();
        if (next[len - 1] != -1 && len % (len - (next[len - 1] + 1)) == 0) {
            return true;
        }
        return false;
    }
};

如果 next[len - 1] != -1,则说明字符串有最长相同的前后缀,如果len % (len - (next[len - 1] + 1)) == 0 ,则说明数组的长度正好可以被 (数组长度-最长相等前后缀的长度) 整除 ,说明该字符串有重复的子字符串。

KMP(前缀表不减一):

class Solution {
public:
    void getNext(int* next, const string& s) {
        int j = 0;
        next[0] = j;
        for (int i = 1; i < s.size(); i++) {
            while (j > 0 && s[j] != s[i]) {
                j = next[j - 1];
            }
            if (s[j] == s[i]) {
                j++;
            }
            next[i] = j;
        }
    }
    bool repeatedSubstringPattern(string s) {
        vector<int> next(s.size());
        getNext(&next[0], s);
        int len = s.size();
        if (next[len - 1] != 0 && len % (len - next[len - 1]) == 0) {
            return true;
        }
        return false;
    }
};

同上。

标签:151,string,int,随想录,next,++,&&,字符串,size
From: https://www.cnblogs.com/kurumaruq/p/18350887

相关文章

  • 代码随想录day32 || 509 斐波那契数列,70 爬楼梯,746 最小代价爬楼梯
    509斐波那契数列funcfib(nint)int{ //dp五部曲 //1dp数组含义以及下标含义:本题保存的是完整的斐波那契数列,i对应数列的第i个数字 //2递推公式:F(n)=F(n-1)+F(n-2) //3dp数组初始化:由递推公式推到,0,1两位需要手动赋值,否则,oor //4遍历顺序:求......
  • 代码随想录算法训练营第十七天(一)| 654.最大二叉树 617.合并二叉树
    654.最大二叉树题目:给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:创建一个根节点,其值为 nums 中的最大值。递归地在最大值 左边 的 子数组前缀上 构建左子树。递归地在最大值 右边 的 子数组后缀上 构建右子树。......
  • 代码随想录算法训练营第十七天(二)| 700.二叉搜索树中的搜索 98.验证二叉搜索树
    700.二叉搜索树中的搜索题目:给定二叉搜索树(BST)的根节点 root 和一个整数值 val。你需要在BST中找到节点值等于 val 的节点。返回以该节点为根的子树。如果节点不存在,则返回 null 。示例1:输入:root=[4,2,7,1,3],val=2输出:[2,1,3]示例2:输入:roo......
  • PTA 7-30 字符串的冒泡排序
    7-30字符串的冒泡排序(20分)我们已经知道了将N个整数按从小到大排序的冒泡排序法。本题要求将此方法用于字符串序列,并对任意给定的K(<N),输出扫描完第K遍后的中间结果序列。输入格式:输入在第1行中给出N和K(1≤K<N≤100),此后N行,每行包含一个长度不超过10的、仅由小写英文字母组成的......
  • 力扣面试经典算法150题:找出字符串中第一个匹配项的下标
    找出字符串中第一个匹配项的下标今天的题目是力扣面试经典150题中的数组的简单题:找出字符串中第一个匹配项的下标题目链接:https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/description/?envType=study-plan-v2&envId=top-interview-......
  • 字符串比较的常用函数
    staticvoidMain(string[]arg){intint1=0;intint2=0;intint3=0;stringstr1="adf";stringstr2="adf";stringstr3="Adf";......
  • 随想录day3:203.移除链表元素|707.设计链表 |206.反转链表
    203.移除链表元素方法一:直接遍历,永远记得处理head,删除链表必须有前驱。/***Definitionforsingly-linkedlist.*publicclassListNode{*intval;*ListNodenext;*ListNode(){}*ListNode(intval){this.val=val;}*ListNode......
  • JAVA 解析html 类型字符串(使用jsoup)
    1.引入pom文件<dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.17.2</version></dependency>2.使用在线解析html工具,自己先看清html内容 (在线推荐:https://coding.tools/cn/html-beautifier#googl......
  • C:一个字符数组里面解析出多个字符串
    一个字符数组里面存放了多个字符串,每个字符串以‘\0’。要求把这些有效字符串筛选出来并输出。 扩展:'\0\0'表示字符串结束。V2方法就是实现的这个扩展功能。 #include<stdio.h>#include<string.h>#include<malloc.h>voidprintSzNameList(charszNameList[],in......
  • 【代码随想录】二、链表:2、设计链表
    部分图文参考于:代码随想录-707.设计链表。这道题目设计链表的五个接口:●获取链表第index个节点的数值●在链表的最前面插入一个节点●在链表的最后面插入一个节点●在链表第index个节点前面插入一个节点●删除链表的第index个节点可以说这五个接口,已经覆盖了链表的......