day-8 代码随想录算法训练营(19)字符串 已二刷

344.反转字符串

思路:一眼双指针
问题:为啥双指针这么快了都才打败58%的人??????????
class Solution {
public:
    void reverseString(vector<char>& s) {
        //思路:哈哈直接双指针
        int right=s.size()-1;
        for(int i=0;i<right;i++)
        {
            char mid=s[i];
            s[i]=s[right];
            s[right]=mid;
            right--;
        }
    }
};
 二刷:双指针
class Solution {
public:
    void reverseString(vector<char>& s) {
        int n=s.size();
        int left=0,right=n-1;
        while(left<right){
            int temp=s[left];
            s[left++]=s[right];
            s[right--]=temp;
        }
    }
};

541.反转字符串II

思路:一次遍历,使用双指针,初始化right=k-1,left=0;先把第一个k反转;当i-right==2k时,
           记录right=i,left+=2*k;
           然后把这个区间内的单词反转
分析:剩余字符小于k时要全部反转,剩余字符大于k小于2*k时反转k;s长度小于2*k时要考虑

!!!剩余字符数大于k小于2*k在遍历中无需考虑。

class Solution {
public:
    void judge(string&s,int left,int right)
    {
        while(left<right)//使用双指针直接反转区间内字符
        {
            char temp=s[left];
            s[left]=s[right];
            s[right]=temp;
            right--;
            left++;
        }
    }
    string reverseStr(string s, int k) {
        int n=s.size();
        if(n<=2*k)//当s长度小于2*k时
        {
            if(n<k)
                judge(s,0,n-1);
            else
                judge(s,0,k-1); 
            return s;
        }
        int left=0,right=k-1;
        judge(s,left,right);//先把前k个单词反转
        for(int i=0;i<n;i++)
        {
            if(i-right==2*k)//每次遍历到需要反转的右区间时
            {
                right=i;
                left+=2*k;
                judge(s,left,right);
            }
            if(i==n-1)//遍历到最后一位时
            {
                if(i-right<2*k)//还没有遍历到反转区间的右区间时
                {
                    left+=2*k;
                    right=i;
                    judge(s,left,right);
                }
            }

        }
        return s;
    }
};
 二刷:同样的思路,判断区间,字符翻转
class Solution {
public:
    void restrs(string& mid,int start,int end){
        end--;
        while(start<end){
            int temp=mid[start];
            mid[start++]=mid[end];
            mid[end--]=temp;
        }
    }
    string reverseStr(string s, int k) {
        int n=s.size();
        int start=0;
        while(start<n){
            int mid=start+k;
            if(n<mid)  restrs(s,start,n); //往后k个数超出范围
            else{//往后k个数没超出范围
                restrs(s,start,mid);
                start+=k;
            } 
            start+=k;
        }
        return s;
    }
};

剑指Offer 05.替换空格

分析:本来想直接替换,但是%20是多位字符,无法直接替换,插入的话后面的字符都要向后移动,相当于增加了时间复杂度。
思路一:使用额外空间复制
class Solution {
public:
    string replaceSpace(string s) {
        string mid="%20",result="";
        for(int i=0;i<s.size();i++)
        {
            if(s[i]==' ')
                result+=mid;
            else
                result+=s[i];
        }
        return result;
    }
};
思路二:不使用额外空间,直接在字符串尾上添加复制
class Solution {
public:
    string replaceSpace(string s) {
        char mids[3]={'%','2','0'};
        int count=0;
        for(int i=0;i<s.size();i++)//查找字符串中空格数
        {
            if(s[i]==' ')
                count++;
        }
        int oldsize=s.size();//原来的长度
        s.resize(s.size()+count*2);//一个空格换为三个字符,每个需要增加两个字符
        int newsize=s.size();//增加后的长度
        int front=oldsize-1,last=newsize-1;
        while(front>=0)
        {
            if(s[front]!=' ')//当扫描到字符时,直接把字符替换到后面
            {
                s[last]=s[front];
            }
            else{//当扫描到空格时,开始用字符填充
                s[last]=mids[2];
                s[--last]=mids[1];
                s[--last]=mids[0];
            }
            last--;
            front--;
        }
        return s;
    }
};
二刷:双指针替换
class Solution {
public:
    string replaceSpace(string s) {
        int n=s.size();
        int midcount=0;
        for(auto it:s){
           if(it==' ') midcount++;//计算空格数量
        }
        int count=midcount*2;//要加入字符的空间
        s.resize(n+count);//增加空间
        int pre=n-1,last=s.size()-1;
        while(pre>=0){
            if(s[pre]!=' ') s[last--]=s[pre];
            else{//遍历到空格时
                s[last--]='0';
                s[last--]='2';
                s[last--]='%';
            }
            pre--;
        }
        return s;

    }
};

 151.翻转字符串里的单词 

思路一:本题做过多次,但是不知如何优化,
class Solution {
public:
    string reverseWords(string s) {
        //思路:倒着遍历,加入结果字符串
        int n=s.size();
        string result="",mid="";
        for(int i=n-1;i>=0;i--)
        {
            if(s[i]!=' ')
            {
                mid=s[i]+mid;
                if(i==0)
                {
                    result+=mid;
                }
            }
            else{
                if(!mid.empty())
                {
                    result+=mid+' ';
                    mid.clear();
                }
            }
        }
        if(result[result.size()-1]==' ')
            result.erase(result.end()-1);
        return result;
    }
};
思路二:看了卡哥的题解是先去掉多余空格,再进行两次翻转,没有对字符串进行增删确实快很多!
二刷:先删除多余空格,然后整个字符串进行翻转,接着逐个字符串进行翻转
class Solution {
public:
    void reverseWord(string &mid,int start,int end){//翻转字符串
        while(start<end){
            char temp=mid[start];
            mid[start++]=mid[end];
            mid[end--]=temp;
        }
    }
    void deletek(string &mid){//删除多余空格
        string str;
        for(auto it:mid){//删除前面和中间的多余空格
            if(str.empty() && it==' ') continue;
            else if(!str.empty() && str.back()==' ' && it==' ') continue;
            str.push_back(it);
        }
        while(str.back()==' ') str.pop_back();//去除尾巴空格
        mid.clear();
        mid=str;
    }
    string reverseWords(string s) {
        deletek(s);//删除多余空格
        reverseWord(s,0,s.size()-1);//翻转整个字符串
        int n=s.size();
        int left=0;
        while(left<n){
            int start=left;
            while(left<n && s[left]!=' ') left++;//找到字符的尾巴
            reverseWord(s,start,left-1);//翻转单个字符串
            left++;
        }
        return s;
    }
};

剑指Offer 58 - II.左旋字符串

class Solution {
public:
    string reverseLeftWords(string s, int n) {
        int m=s.size();
        if(n>=m)
            return s;
        string mid="",result="";
        for(int i=0;i<m;i++)
        {
            if(i<=n-1)
            {
                mid+=s[i];
            }
            else
                result+=s[i];
        }
        result+=mid;
        return result;
    }
};
二刷:我真牛逼
class Solution {
public:
    string reverseLeftWords(string s, int n) {
        int len=s.size();
        for(int i=0;i<n;i++) s.push_back(s[i]);
        return s.substr(n);
    }
};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值