五、字符串相关题目记录

学习来源:
代码随香炉:https://www.programmercarl.com/
labuladong算法:https://labuladong.github.io/algo/

字符串

把字符串转换成整数(atoi)

思路:
既然是将字符串转化为数字,那我们可以遍历字符串,一个字符串,一个字符地检查,然后取出掉无用的,取出数字,利用如下代码,一个数字一个数字地转换,前面的扩大十倍加上后面一位。

res = res * 10 + sign * (c - ‘0’);

具体做法:
step 1:遍历字符串,用index记录全程的下标。
step 2:首先要排除空串,然后越过前导空格,以及前导空格后什么都没有就返回0.
step 3:然后检查符号,没有符号默认为正数。
step 4:再在后续遍历的时候,将数字字符转换成字符,遇到非数字则结束转换。
step 5:与Int型最大最小值比较,检查越界情况。

class Solution {
public:
    int StrToInt(string s) {
        int res = 0;
        int index = 0;
        int n = s.length();
        //去掉前导空格,如果有
        while(index < n){ 
            if(s[index] == ' ')
                index++;
            else
                break;
        }
        //去掉空格就什么都没有了
        if(index == n) 
            return 0;
        int sign = 1;
        //处理第一个符号是正负号的情况
        if(s[index] == '+')
            index++;
        else if(s[index] == '-'){
            index++;
            sign = -1;
        }
        //去掉符号就什么都没有了
        if(index == n) 
            return 0;
        while(index < n){
            char c = s[index];
            //后续非法字符,截断
            if(c < '0' || c > '9')  
                break;
            //处理越界
            if(res > INT_MAX / 10 || (res == INT_MAX / 10 && (c - '0') > INT_MAX % 10))
            
                return INT_MAX;
            if(res < INT_MIN / 10 || (res == INT_MIN / 10 && (c - '0') > -(INT_MIN % 10)))
                return INT_MIN;
            res = res * 10 + sign * (c - '0');
            index++;
        }
        return res;
    }
};

反转字符串

utility iostream algorithm 都有 swap c++11改在了al…
双指针 交换首尾

class Solution {
public:
    void reverseString(vector<char>& s) {
        int i = 0;
        int j = s.size()-1;
        while(i<=j){
            swap(s[i],s[j]);
            i++;
            j--;
        }
    }
};

反转字符串II (每2k 对前k 个字符反转)

其实在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。
当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章。

在这里插入图片描述

所以当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章。

在这里插入图片描述

替换空格 (用%20替换’ ')

请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
// 统计空格的个数 // 扩充字符串s的大小,也就是每个空格替换成"%20"之后的大小
// 从后先前将空格替换为"%20"

1. 使用额外的辅助空间:

class Solution {
public:
    string replaceSpace(string s) {
        string str;
        for(auto c:s){
            if(c==' '){
                str+="%20";
            }else{
                str+=c;
            }
        }
        return str;
    }
};

2. 不适用额外辅助空间

在这里插入图片描述

翻转字符串中的单词

(代码较多 细节)
先移除多余空格 再反转整个字符串 然后再翻转单词 (整体+局部)

  1. split函数分割,然后反转,再join
#include<sstream>
istringstream sin(string);
while(gelint(sin,str,',')){
    res.push_back(str);
}
  1. 双指针
    思路: 整体翻转+ 局部翻转
    • 移除多余空格
    • 将整个字符串反转
    • 将每个单词反转
// 版本一
class Solution {
public:
    // 反转字符串s中左闭又闭的区间[start, end]
    void reverse(string& s, int start, int end) {
        for (int i = start, j = end; i < j; i++, j--) {
            swap(s[i], s[j]);
        }
    }

    // 移除冗余空格:使用双指针(快慢指针法)O(n)的算法
    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 > 0
                    && s[fastIndex - 1] == s[fastIndex]
                    && s[fastIndex] == ' ') {
                continue;
            } else {
                s[slowIndex++] = s[fastIndex];
            }
        }
        if (slowIndex - 1 > 0 && s[slowIndex - 1] == ' ') { // 去掉字符串末尾的空格
            s.resize(slowIndex - 1);
        } else {
            s.resize(slowIndex); // 重新设置字符串大小
        }
    }

    string reverseWords(string s) {
        removeExtraSpaces(s); // 去掉冗余空格
        reverse(s, 0, s.size() - 1); // 将字符串全部反转
        int start = 0; // 反转的单词在字符串里起始位置
        int end = 0; // 反转的单词在字符串里终止位置
        bool entry = false; // 标记枚举字符串的过程中是否已经进入了单词区间
        for (int i = 0; i < s.size(); i++) { // 开始反转单词
            if (!entry) {
                start = i; // 确定单词起始位置
                entry = true; // 进入单词区间
            }
            // 单词后面有空格的情况,空格就是分词符
            if (entry && s[i] == ' ' && s[i - 1] != ' ') {
                end = i - 1; // 确定单词终止位置
                entry = false; // 结束单词区间
                reverse(s, start, end);
            }
            // 最后一个结尾单词之后没有空格的情况
            if (entry && (i == (s.size() - 1)) && s[i] != ' ' ) {
                end = i;// 确定单词终止位置
                entry = false; // 结束单词区间
                reverse(s, start, end);
            }
        }
        return s;
    }
    
};

左旋字符串(把前n个字符串移动到末尾)

在这里插入图片描述

局部翻转 + 整体翻转 = 左旋转
具体步骤为:
反转区间为前n的子串
反转区间为n到末尾的子串
反转整个字符串

class Solution {
public:
    string reverseLeftWords(string s, int n) {
        reverse(s.begin(), s.begin() + n);
        reverse(s.begin() + n, s.end());
        reverse(s.begin(), s.end());
        return s;
    }
};

实现strStr() (KMP算法)

在这里插入图片描述

前缀:包含首字母不包含尾字母的所有串
后缀:包含尾字母不包含首字母的所有串
前缀表: next数组 遇到冲突 告诉我们回退到哪里

最长相等前后缀:

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

在这里插入图片描述

重复的子字符串 (s可以由多个串重复得到)

在这里插入图片描述

字符串相乘 (数字乘法)

数字太大,直接相乘会发生益处,因此采用数字乘法进行。

在这里插入图片描述
在这里插入图片描述

  • 索引从0开始
    num1[i] 和 num2[j] 的乘积对应的就是 res[i+j] 和 res[i+j+1] 这两个位置。

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ray Song

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值