代码随想录刷题记录(8)| 字符串(151.反转字符串里的单词,卡码网:55.右旋转字符串,28. 找出字符串中第一个匹配项的下标,459.重复的子字符串,字符串总结,双指针回顾)

目录

(四)反转字符串里的单词

1.  题目描述

2. 思路

3. 解题过程

(1)使用额外空间存储

(2)原地反转 

(五)右旋转字符串

1. 题目描述

2. 思路

3. 解题过程

 (六)找出字符串中第一个匹配项的下标

1. 题目描述

2. 思路

3. 解题思路

(七)重复的子字符串

1. 题目描述

2. 思路

3. 解题过程

(八)总结


(四)反转字符串里的单词

151. 反转字符串中的单词 - 力扣(LeetCode)

1.  题目描述

        给你一个字符串 s ,请你反转字符串中 单词 的顺序。

        单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。

        返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。

        注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

2. 思路

  1. 移除多余空格
  2. 将整个字符串反转
  3. 将每个单词反转

3. 解题过程

难易程度:中等

标签:双指针、字符串

(1)使用额外空间存储

        先把单词存在字符串数组,然后从后往前存到结果字符串中返回。

class Solution {
public:
    string reverseWords(string s) {
        vector<string> words;
        // 把每个单词存下来
        for(int i = 0; i < s.size(); i++){
            string temp;
            while(i < s.size() && s[i] != ' '){
                temp += s[i++];
            }
            if(temp.size()){
                words.push_back(temp);
            }
        }
        string result;
        for(int i = words.size() - 1; i > 0; i--){
            result += words[i] + ' ';
        }
        result += words[0];
        return result;
    }
};

 

(2)原地反转 
class Solution {
public:
    // 去除多余的空格
    void RemoveSpace(string &s){
        int slow = 0, fast = 0;
        while(fast < s.size()){
            if(s[fast] != ' '){
                // slow!=0时,不是第一个单词,在前面加空格
                if(slow){
                    s[slow++] = ' ';
                }
                while(fast < s.size() && s[fast] != ' '){
                    s[slow++] = s[fast++];
                }
            }
            fast++;
        }
        s.resize(slow);
    }

    string reverseWords(string s) {
        RemoveSpace(s);
        // 反转整个字符串
        reverse(s.begin(), s.end());
        // 反转每个单词
        int start = 0;
        for(int i = 0; i <= s.size(); i++){
            if(i == s.size() || s[i] == ' '){
                reverse(s.begin() + start, s.begin() + i);
                start = i + 1;
            }
        }
        return s;
    }
};

 

(五)右旋转字符串

55. 右旋字符串(第八期模拟笔试) (kamacoder.com)

1. 题目描述

        字符串的右旋转操作是把字符串尾部的若干个字符转移到字符串的前面。给定一个字符串 s 和一个正整数 k,请编写一个函数,将字符串中的后面 k 个字符移到字符串的前面,实现字符串的右旋转操作。 

        例如,对于输入字符串 "abcdefg" 和整数 2,函数应该将其转换为 "fgabcde"。

 

2. 思路

        先把字符串整体反转,然后再分别反转前 k 个,和剩余部分。

3. 解题过程

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

int main(){
    int k;
    cin >> k;
    string s;
    cin >> s;
    reverse(s.begin(), s.end());
    reverse(s.begin(), s.begin() + k);
    reverse(s.begin() + k, s.end());
    cout << s;
    return 0;
}

 

 (六)找出字符串中第一个匹配项的下标

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

1. 题目描述

        给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回  -1 

 

2. 思路

        kmp算法。

        前缀表(prefix table)记录下标i之前(包括i)的字符串中,有多大长度的相同前缀后缀。前缀表是用来回退的,当模式串与主串(文本串)不匹配的时候,将模式串回退到前一个字符的前缀表的数值位置处。

        next数组可以是前缀表,但是很多实现都是把前缀表统一减一(右移一位,初始位置为-1)之后作为next数组。构造next数组其实就是计算模式串s,前缀表的过程。 主要有如下三步:

  1. 初始化
  2. 处理前后缀不相同的情况
  3. 处理前后缀相同的情况

 

3. 解题思路

难易程度:简单

标签:双指针、字符串、字符串匹配

之后再补。。。

 

(七)重复的子字符串

459. 重复的子字符串 - 力扣(LeetCode)

1. 题目描述

        给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。

2. 思路

假设字符串s使用多个重复子串构成(这个子串是最小重复单位),重复出现的子字符串长度是x,所以s是由n * x组成。

因为字符串s的最长相同前后缀的长度一定是不包含s本身,所以 最长相同前后缀长度必然是m * x,而且 n - m = 1,(这里如果不懂,看上面的推理)

所以如果 nx % (n - m)x = 0,就可以判定有重复出现的子字符串。

3. 解题过程

难易程度:简单

标签:字符串、字符串匹配 

暂时跳过 

(八)总结

        字符串是若干字符组成的有限序列,也可以理解为是一个字符数组,在C语言中,把一个字符串存入一个数组时,也把结束符 '\0' 存入数组,并以此作为该字符串是否结束的标志。vector< char > 和 string 在基本操作上没有区别,但是 string 提供更多的字符串处理的相关接口,例如string 重载了 +,而 vector 却没有。

  • 19
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值