代码随想录算法训练营第八天|344.反转字符串、541.反转字符串II、剑指Offer 05.替换空格、151.反转字符串里的单词、剑指Offer58-II.左旋转字符串

344.反转字符串

344.反转字符串

代码随想录(programmercral.com)

字符串基础操作! | LeetCode:344.反转字符串

思路

直接把字符串看作线形表的顺序存取结构,反转字符串相当于逆置数组。

代码实现

class Solution {
public:
    void reverseString(vector<char>& s) {
        //直接当做数组处理,相当于逆置数组
        int i=0,j=s.size()-1;
        while(i<j){
            char temp=s[i];
            s[i]=s[j];
            s[j]=temp;
            i++;
            j--;
        }

    }
};

时间复杂度o(n)空间复杂度o(1)

541.反转字符串II

541.反转字符串II

代码随想录(programmercral.com)

字符串操作进阶! | LeetCode:541. 反转字符串II

思路

思路很容易,也就是在反转字符串的基础上加了一些限制条件,关键在于如何 才可以让代码更加简洁,优化在于for循环中的条件,正常情况下是i++,但是这里反转字符串是以2*k为单位的,所以可以让i+=2*k,吧2*k看作成一个小整体,然后一个小块一个小块的处理,最后在看剩下的一小部分是小于k还是大于等于k小于2k

代码实现:自己实现的版本

class Solution { public: string reverse(string s,int start,int end){ int i=start,j=end-1; while(i<j){ char temp =s[i]; s[i]=s[j]; s[j]=temp; i++;j--; } return s; } string reverseStr(string s, int k) { //写的太麻烦了 int i=0,j=2*k; while(j<s.size()){ s=reverse(s,i,i+k); j+=2*k; i+=2*k; } if(s.size()-i<k){ s=reverse(s,i,s.size()); } else if(s.size()-i>=k&&s.size()-i<=2*k){ s=reverse(s,i,i+k); } return s; } };

代码实现:优化版本 把while写成了一个for

class Solution {
 public: 
    string reverse(string s,int start,int end){ 
        int i=start,j=end-1; 
        while(i<j){ 
            char temp =s[i]; 
            s[i]=s[j]; 
            s[j]=temp;
            i++;j--; 
        } 
            return s; 
    } 
    string reverseStr(string s, int k) {
     //简洁版本 上述逻辑可以用一个for循环实现 
        for(int i=0;i<s.size();i+=2*k){ 
            if(i+k<=s.size()) s=reverse(s,i,i+k); 
            else s=reverse(s,i,s.size()); 
        } 
        return s; 
    }
};

时间复杂度o(n)空间复杂度o(1)

剑指Offer 05.替换空格

剑指Offer 05.替换空格

代码随想录(programmercral.com)

思路:双指针法

先统计空格的数量,然后增长原字符串的长度,扩展好长度以后,使用双指针把空格替换为%20,具体操作为,先让一个指针i指向原字符串尾,然后j指向扩展后的字符串尾,从后向前处理(为什么从后向前,因为从前向后处理时间复杂度是o(n^2)因为为了保证顺序表的线性结果,替换过程中需要移动元素)如果i扫描到的不是空格,那么就直接覆盖到j所指的位置,如果是空格,那么j顺序插入0,2,%,然后重复上述操作,直到i小于0,就替换完成了。

代码实现

class Solution {
public:
    string replaceSpace(string s) {
        //双指针 
        int count=0;
        int oldsize=s.size();
        for(int i=0;i<s.size();i++){
            if(s[i]==' ') count++;
        }
        s.resize(s.size()+2*count);
        int i=oldsize-1,j=s.size()-1;
        for(;i>=0;i--){
            if(s[i]!=' ')s[j--]=s[i];
            else{
                s[j--]='0';
                s[j--]='2';
                s[j--]='%';
            }
        }
        return s;
    }
};


//时间复杂度o(n)空间复杂度o(1);

151.反转字符串里的单词

151.反转字符串里的单词

代码随想录(programmercral.com)

字符串复杂操作拿捏了! | LeetCode:151.翻转字符串里的单词

思路

就是把反转字符串,移除数组中的元素综合在了一起,思路不难,关键在于代码如何实现

代码实现:自己实现的冗余版本

class Solution { public: string reverse(string s,int start,int end){ int i=start,j=end-1; while(i<j){ char temp=s[i]; s[i]=s[j]; s[j]=temp; i++;j--; } return s; } string deletekg(string s){ int count=0;//前导空格的数量 while(s[count]==' '){ count++; } int i=0,j=count; for(;j<s.size();j++){ s[i++]=s[j]; } s.resize(i); return s; } string deleteinkg(string s){ int i=s.size()-1,j=s.size()-1; int count=0; while(i>=0){ while(s[i]==s[i+1]&&s[i]==' '){ count++; i--; } s[j--]=s[i--]; } while(count--) s[count]=' '; s=deletekg(s); return s; } string reverseWords(string s) { //先去掉前导空格,先整体反转,然后从头扫描,碰到一个单词就反转一次,再去掉前导空格 s=deletekg(s); s=reverse(s,0,s.size()); s=deletekg(s); int last=0;//上次空格之后的第一个字母的位置 for(int i=0;i<s.size();i++){ if(s[i]==' '){ s=reverse(s,last,i); last=i+1; } } s=reverse(s,last,s.size());//最后扫不到空格了 所以最后一个单词会漏处理掉 s=deleteinkg(s); return s; } };

代码实现:运用了移除数组元素的双指针操作优化了去除空格的操作

class Solution {
public:
    string reverse(string s,int start,int end){
        int i=start,j=end-1;
        while(i<j){
            char temp=s[i];
            s[i]=s[j];
            s[j]=temp;
            i++;j--;
        }
        return s;
    }
    string reverseWords(string s) {
        //简介版代码 关键在于优化了去除空格的操作 ,如何优化的和数组中的移除元素同理,使用双指针移动
        int slow=0;
        for(int fast=0;fast<s.size();fast++){
            if(s[fast]!=' '){
                if(slow!=0) s[slow++]=' ';//除了第一个单词,在每个单词前面插入一个空格
                while(fast<s.size()&&s[fast]!=' '){
                    s[slow++]=s[fast++];
                }
            }
        }
        s.resize(slow);
        s=reverse(s,0,s.size());
        int last=0;//上次空格之后的第一个字母的位置
        for(int i=0;i<s.size();i++){
            if(s[i]==' '){
                s=reverse(s,last,i);
                last=i+1;
            }
        }
        s=reverse(s,last,s.size());//最后扫不到空格了 所以最后一个单词会漏处理掉
        return s;
    }

时间复杂度o(n)空间复杂度o(1)

剑指Offer58-II.左旋转字符串

剑指Offer58-II.左旋转字符串

代码随想录(programmercral.com)

思路

 先整体转置,然后转置0到size-n,再转置size-n到size即可完成旋转操作

代码实现

class Solution {
public:
    string reverse(string s,int start,int end){
        int i=start,j=end-1;
        while(i<j){
            char temp=s[i];
            s[i]=s[j];
            s[j]=temp;
            i++;j--;
        }
        return s;
    }
    string reverseLeftWords(string s, int n) {
        s=reverse(s,0,s.size());
        s=reverse(s,0,s.size()-n);
        s=reverse(s,s.size()-n,s.size());
        return s;

    }
};


时间复杂度o(n)空间复杂度o(1)

总结

今天的三个题没有难的算法思路,需要注意的就是一个对于字符串的操作的优化,例如移除数组元素的双指针法怎么运用到151题中的去除空格中,还有在541题中用for实现while的操作。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值