代码随想录算法训练营Day8 | 344.反转字符串● 541. 反转字符串II● 卡码网:54.替换数字● 151.翻转字符串里的单词● 卡码网:55.右旋转字符串

今天的题目写了很久。特别是翻转字符串里的单词这题,想了一两个小时,一直在试,后面实在是不行了,就去看了视频和文章讲解,一起来看今天的题目吧!

344.反转字符串 代码随想录

首先是这道题,这道题实在是太过于简单了。双指针,直接用就行了,代码就不粘上来了,看下一题

541. 反转字符串II:代码随想录

这到题就有很多可以来说的点了,一起来看,这题的意思是给你一个字符串,再给你一个数k,让你不断计数,当计数到2k时,将前k个数进行一个翻转,然后继续此过程,直到剩余的数不足2k时,如果此时剩余的数大于k,就将前k个数进行翻转,如果不足k个数,就将所有的数都进行翻转,这道题啊,我一开始做的非常复杂,后面还是做不出来,看了视频才知道原来还可以这么写,我在for循环中呢,将i每次循环完都加上2*k,在循环内部,我判断此时i的位置加上k之后有没有超过字符串的大小,如果超过了,就说明后面的字符不足k个,此时,就将后面所有的字符都进行一个翻转,如果大于呢,就将前k个字符做一个翻转,在continue,随后i+=2k,进行下一次翻转,我觉得这个方法真的很巧妙,不像我每次都想着分很多种情况去讨论,这样很难去做到bugfree,我应该去总结共同性,尽量减少讨论的次数,这也往往是很多题目的正解,就是看你有没有这个分析能力,能够找到它们的共同性,能不能总结出一个像公式一样的解法,就像一个算法一样,一个函数一样,你传进去一个参数,它对应的就传出一个你想要的结果,并在其中解决了你的问题,浙才是重点,所以我以后写题目,应该要多加分析,总结共性,然后再去编写代码,而不是一上来就将所有的情况罗列一遍,有感而发,继续回来,来看具体代码的实现

class Solution {
public:
    string reverseStr(string s, int k) {
        for(int i=0;i<s.size();i+=2*k){
            if(i+k<s.size()){
                s=reverse(s,i,i+k-1);
                continue;
            }
            s=reverse(s,i,s.size()-1);
        }
        return s;
    }
    string reverse(string  s, int from, int to){
        for(;from<to;){
            swap(s[from++],s[to--]);
        }
        return s;
    }
};

正如我上面所说,这就是主函数的实现,下面是我自己编写的reverse函数,主要是你传进去三个参数,其中的from和to分别代表你要在字符串里做翻转操作的起点和终点下标,随后就是经典的双指针法,可以自己看,这里不做过多的阐述,来看下一题;

卡码网:54.替换数字 代码随想录

这道题非常简单,但是如果我要求你的空间复杂度为1呢,你会如何去实现它,这里就不得不称赞代码随想录里讲的方法了,这个方法非常的巧妙,先来看代码

#include<bits/stdc++.h>
using namespace std;
int main(){
    string s;
    cin>>s;
    int count=0;int x=s.size()-1;
    for(int i=0;i<s.size();i++){
        if(s[i]>='0' && s[i]<='9') count++;
    }
    s.resize(s.size()+count*5);
    int y=s.size()-1;
    while(x>=0){
        if(s[x]>='0' && s[x]<='9'){
            s[y--]='r';
            s[y--]='e';
            s[y--]='b';
            s[y--]='m';
            s[y--]='u';
            s[y--]='n';
        }
        else{
            s[y--]=s[x];
        }
        x--;
    }
    cout<<s<<endl;
    return 0;
}

首先呢,我先定义一个count用来计数看这个字符串里有多少个数字,然后再定义一个数x用来记录一开始的字符串最后一个元素的位置,然后我用内置函数resize重新定义它的大小为s.size()+count*5;这样的话,我们就可以在原来的字符串上进行操作,而不用申请新的内存空间,然后再定义一个数y为新字符串的最后一位置,在原来的字符串没有遍历完,也就是x>=0时,如果x所对应的元素值为数字,那么就在y的位置上依次向前加上number,如果不是那就直接在y的位置上放入对应的值即可,注意这里为什么要从后往前去放元素呢,因为如果你从前往后加入元素的话,就要不断把后面的元素往后移,这样时间复杂度就变成n^2了,所以要从后往前放入元素

151.翻转字符串里的单词:代码随想录

这道题,可以说是今天的重中之重,来好好看看这道题,这道题目的意思就是你要将给你的字符串里的所有单词都反转一遍,然后字符串里还会有多余的空格,你必须要控制字符串里的空格只有相邻的两个单词之间有,那么这道题我们怎么来做呢,再看完题解后我的做法是这样的,首先先将字符串里的每一个单词都反转一遍,然后再将整个字符串翻转一遍,最后再来处理空格的问题,来看具体代码的实现

class Solution {
public:
    string reverseWords(string s) {
       for(int i=0;i<s.size();i++){
            if(s[i]!=' '){
                int k=i;
                while(s[k]!=' ' && k<s.size()){
                    k++;
                }
                s=reverse(s,i,k-1);
                i=k;
            }
       }
       s=reverse(s,0,s.size()-1);
       int slow=0;int fast=0;
       while(fast<s.size() && s[fast]==' ' && s.size()>0){
            fast++;
       }
       for(;fast<s.size();fast++){
            if(fast-1>=0 && s[fast]==' ' && s[fast-1]==' '){
                continue;
            }else{
                s[slow++]=s[fast];
            }
       }
       if(slow-1>=0 && s[slow-1]==' '){
            s=s.substr(0,slow-1);
       }
       else{
            s.resize(slow);
       }
       return s;
    }
    string reverse(string s, int from ,int to){
        for(;from<to;){
            swap(s[from++],s[to--]);
        }
        return s;
    }
};

首先就是如何翻转字符串里的单词,我们先来找到第一个不是空格的字符,然后用一个while循环来找到它最后一个字符的下标,然后调用我们自定义的reverse函数,再循环的进行的条件中,还要注意下标越界的问题,然后再翻转整个字符串,然后就是用双指针法来去除字符串中空格,首先去除开头的空格,在为‘ ’时不断加加,同时注意下标越界的问题,然后就是单词之间的空格,在fast-1>0 && s[fast]==' ' && s[fast-1]==' '时,代表这个空格是我们需要去删除的所以让fast直接跳过这个元素,因为fast指向的是我们需要的元素,否则的话,就让s[slow++]=s[fast];将其加入到字符串中,当遍历完后,我们需要删除字符串后面的空格,同样是while循环,同时注意下标越界的问题,,然后因为我们删除了很多元素,所以,问问我们要重新定义数组的大小,因为slow表示的是我需要的元素所存放的位置,所以大小就是slow;最后返回即可,这就是这道题目的解答,整个过程我已经说得非常的清楚了,但是这个思路第一次自己写是真的想不出来,只能去看题解,继续加油吧,来看下一题

卡码网:55.右旋转字符串 代码随想录

这道题同样很简单,但是如果我要求你只能使用空间复杂度为1呢,你会如何来做,这里我不得不说人类的智慧你真的难以想象,真的太聪明了,你想想给你字符串abcdefg,和n为2,让你将其变成fgabcde,我们可以先将整个字符串做一个翻转,这样就变成了gfedcba,再将前n个字符翻转,再将后面的字符翻转,就得到了fgabcde,知道思路了,那代码写起来就是easy了,来看具体代码的实现

#include<bits/stdc++.h>
using namespace std;
int main(){
    string s;int n;
    cin>>n;
    cin>>s;
    for(int i=0;i<s.size()/2;i++){
        swap(s[i],s[s.size()-i-1]);
    }
    int left=0;int right=n-1;
    for(;left<right;){
        swap(s[left++],s[right--]);
    }
    int slow=n;int fast=s.size()-1;
    for(;slow<fast;){
        swap(s[slow++],s[fast--]);
    }
    cout<<s<<endl;
    return 0;
}

这就是今天的任务,最后送给大家一句话

编程技术日新月异,保持持续学习和自我提升是成为一名优秀程序员的关键!人活着就是为了coding!!!!

  • 22
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值