字符串-算法总结

目录

反转字符串

替换空格

翻转字符串里的单词

左旋字符串

KMP

重复的字符字串



反转字符串

原理:

对于字符串在原地翻转问题,可以reverse。但是其本质我们可以知道是利用双指针方法。一个指向开始,一个指向结束,不断交换两个指针的值,这里交换可以用swap,或者中间变量交换。

代码如下:

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

相关题目:
344. 反转字符串 - 力扣(LeetCode)https://leetcode.cn/problems/reverse-string/541. 反转字符串 II - 力扣(LeetCode)https://leetcode.cn/problems/reverse-string-ii/

替换空格

方法:

我们主要是先计算出扩充之后的大小,以及从后遍历数组解决数据不移动问题。

统计需要扩充的大小

        int count = 0;
        int oldWidth = s.size();
        for(int i = 0; i < s.size(); i++){
            if(s[i] == ' '){
                count++;
            }
        }
        int newWidth = s.size() + count * 2;
        s.resize(newWidth);

定义两个指针,一个是旧数组末尾,一个是新数组末尾。如果不是空格,两个同时--。当遇到空格,新指针一次性移动三位,并且填充三位。

        //从后往前遍历
        for(int i = oldWidth - 1,  j = newWidth - 1; i < j; j--, i--){
            if(s[i] != ' '){
                s[j] = s[i];
            }
            else{
                s[j] = '0';
                s[j - 1] = '2';
                s[j - 2] = '%';
                j -= 2;
            }

完整代码:

class Solution {
public:
    string replaceSpace(string s) {
        int count = 0;
        int oldWidth = s.size();
        for(int i = 0; i < s.size(); i++){
            if(s[i] == ' '){
                count++;
            }
        }
        int newWidth = s.size() + count * 2;
        s.resize(newWidth);
        //从后往前遍历
        for(int i = oldWidth - 1,  j = newWidth - 1; i < j; j--, i--){
            if(s[i] != ' '){
                s[j] = s[i];
            }
            else{
                s[j] = '0';
                s[j - 1] = '2';
                s[j - 2] = '%';
                j -= 2;
            }
        }
        return s;
        }
       
    
};

相关题目:

剑指 Offer 05. 替换空格 - 力扣(LeetCode)https://leetcode.cn/problems/ti-huan-kong-ge-lcof/

翻转字符串里的单词

方法:

思路为:去除空格,翻转字符串,对每个单词再进行翻转。

去除空格:双指针实现。首先遍历整个字符串。当遇到非‘ ’时,把快指针遍历的元素插入慢指针对应的下标。

注意:我们对于中间的单词是需要空格的,因此我们会在不是第一个起始位置的地方插入一个空格,然后开始后续的插入非空格元素。

翻转字符串:遍历字符串,利用swap进行交换

单词翻转:利用计数器。遍历整个字符串,当计数器遇到单词边界或者字符串边界时,翻转计数器对应的单词。然后更新计数器,继续找下一个单词。

整个代码如下:

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++];
                }
            }
        }
        return 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(i == s.size() || s[i] == ' '){
                //当i移动到边界或者碰到单词边界
                reverse(s, start, i - 1);
                start = i + 1;
            }
        }
        return s;
    }
};

相关题目:
151. 反转字符串中的单词 - 力扣(LeetCode)https://leetcode.cn/problems/reverse-words-in-a-string/

左旋字符串

方法:

 按照上图进行翻转即可。

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;
    }
};

KMP

1.当遇到不匹配时,根据前缀表找到最长相等前后缀后,只需要从前面那个位置重新开始找,因为重新找的位置满足了前面的相同。

class Solution {
public:
    void getNext(int* next,const string&s){
        int j=0;
        next[0]=0;
        for(int i=1;i<s.size();i++){
            //把j回退到next数组下标的地方
            while(j>0&&s[i]!=s[j]){
                j=next[j-1];
            }
            //相同的话,j就前移继续判断
            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;
    }
};

重复的字符字串

class Solution {
public:
    bool repeatedSubstringPattern(string s) {
        //find返回的s的首字母下标
        //find返回时,如果是不能重复的,则返回大小比原来大1
        //如果可以重复,则返回大小比原来下
        return (s + s).find(s, 1) < s.size();

    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值