代码随想录(day8)——字符串

Leetcode.344 反转字符串:

344. 反转字符串 - 力扣(LeetCode)

原理过于简单,没什么好说的,直接给出代码:

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

    }
};


Leetcode.541 反转字符串:

541. 反转字符串 II - 力扣(LeetCode)

       对于本题,题干中的条件看起来十分复杂,其实可以归结于一种分支情况,即每次都读取给定字符串s中的前2k个字符,反转前k个。即:

       而下面的两行则只是针对字符串中的剩余字符。如果剩余字符的数量少于k则全部反转,否则反转前k个。

       由于对于字符串的反转,每次都是以2k来进行的,所以,在遍历整体的字符串时,每次都遍历2k个字符,再对这些字符进行操作。由于每当读取2k字符和剩余字符的数量n,k<n<2k时,都是反转k个字符,所以这两种情况可以归为一类。即:判断已被操作的区间+k是否满足<=s.size(),满足的话,则反转这段区间的前k字符,否则说明剩余字符的数量<k,因此,直接对剩余的字符全部进行反转即可。

class Solution {
public:
    string reverseStr(string s, int k) {
        
    for(int i = 0; i < s.size(); i+=2*k)
    {
        if(i + k <= s.size())
        {
            reverse(s.begin()+i,s.begin()+i+k);
        }
        else
        {
            reverse(s.begin()+i,s.begin()+s.size());
        }
    } 

    return s;   
    }
};

卡码网.54 替换数字:

54. 替换数字(第八期模拟笔试) (kamacoder.com)

对于本题,可以直接利用string中的运算符重载"+="以及开辟一个新的string类对象来完成,但是这种方法需要开辟新的空间,且过于简单,意义不大,因此对于这种方法本处只给出代码,重点在于下面的第二种方法:

#include<string>
#include<iostream>
using namespace std;

int main()
{
   string s1,s2;
   cin >> s1;
   
   for(int i = 0; i < s1.size(); i++)
   {
       if(s1[i] >= '0' && s1[i] <= '9')
       {
           s2+="number";
       }
       else
       {
           s2+=s1[i];
       }
   }
   cout << s2;
   
    return 0;
}

运行结果如下:

       对于第二种方法,可以首先遍历一遍给定的字符串,并且创建一个变量count用于统计给定字符串中出现数字的次数。在遍历完成后,直接利用resize函数对给定字符串进行扩容,扩容大小为s1.size()-count+count*6,即s.size()+5*count。此时的字符串的大小就等于将所有的数字都改为number后的字符串的大小。

     然后利用双指针对字符串进行遍历,一个指针fast指向现字符串的末尾,另一个指针slow指向原字符串最后一个字符所在的位置。例如对于字符串a1b2c3,由于字符串中存在三个数字,因此count==3,在扩容时,大小为3+5*3 = 18。双指针指向的位置如下图所示:

如果slow位置所对应的字符是数字,则从fast位置开始,依次向前填写number的每个字母,即:

在完成对于number的倒序填写后,令fast--,slow--,即:

再对slow位置的字符进行判断,由于不为数字,因此s[fast]=s[slow];fast位置进行赋值。即:

随后再fast--,slow--。依次循环即可。

对应代码如下:

#include<string>
#include<iostream>
using namespace std;

int main()
{
   string s1;
   cin >> s1;
   int count = 0;
   for(int i = 0; i < s1.size(); i++)
   {
       if(s1[i] >= '0' && s1[i] <= '9')
       {
           count++;
       }
   }
   
   int oldlen = s1.size()-1;
   int slow = oldlen;
   s1.resize(s1.size()+5*count);
   int fast = s1.size()-1;
   for(; fast >=0; fast--)
   {
       if(s1[slow] >= 'a' && s1[slow] <= 'z')
       {
           s1[fast] = s1[slow];
       }
       else 
       {
           s1[fast] = 'r';
           s1[fast-1] = 'e';
           s1[fast-2] = 'b';
           s1[fast-3] = 'm';
           s1[fast-4] = 'u';
           s1[fast-5] = 'n';
           fast-=5;
       }
       slow--;
   }
   
   cout <<s1;
   return 0;
}

Leetcode.151 反转字符串中的单词:

151. 反转字符串中的单词 - 力扣(LeetCode)

        对于本题,与文章C及C++每日练习(2)-CSDN博客中倒置字符串一题极为相似,但是对于本题,单词之间的空格并不是只有一个,而是若干个。因此,解决本题的方法可以分为两步:

1.将给定字符串中的多余的空格进行删除。

2.按照C及C++每日练习(2)-CSDN博客中的方法倒置字符串中的单词

对于如何删除字符中多余的空格,例如对于下面给定的字符串:

对于多余的字符,分别为第一个字符前面的空格和最后一个字符后面的空格,以及两个单词之前非第一个空格。对于消除多余的字符,可使用的方法如下:

利用for循环对字符串进行遍历,同时创建两个指针slow,fast.在循环中,只对s[fast] !=" "的情况进行处理,如果s[fast] ==" \, \, ";则令fast继续向后遍历。例如对于上面图中的字符串,slow,fast的起始位置如下所示:

s[fast]!="\, \, \, ";时,即:

s[slow] = s[fast],并且两个指针向后移动一位,即:

按照上述方法,利用while循环完成对于单个字符或者字符串的覆盖,即:

  while(fast < s.size() && s[fast] != ' ')
            {
                s[slow++] = s[fast++];
            }

而对于多余空格的处理,可以再循环开头单独进行判定:判定条件如下:
s[fast] !=' \, \, \, ' , slow !=0;,例如对于上面图中slow所处的位置是待处理的多余空格。由于处理多个空格的条件为s[fast] !=' \, \, \, ' , slow !=0;,因此按照前面对于fast运动逻辑的规定,fast会继续向下遍历,直到找到非空字符,即:

此时,改变slow位置的字符,即:s[slow] = '\, \, ';,然后让slow指向下一个位置,即:

随后,再利用前面的逻辑使得s[slow]=s[fast]来复写非空字符串,即:

再按照前面的规则,首先让fast移动至非空字符,即:

s[slow++]='\, \, ';,即:

再复写非空字符串,即:

完成了对于字符串的去重操作。随后,利用resize函数,将字符串的长度改为slow

对于旋转字符串的方法,可以在C及C++每日练习(2) 进行查看,本处只给出相应代码:
 

class Solution {
public:

    void removeExtraSpace(string&s)
    {
       int slow = 0, fast = 0;
       for(fast= 0;fast < s.size(); fast++)
       {
        if(s[fast] != ' ')
        {
            if(slow != 0)
            {
                s[slow] = ' ';
                slow++;
            }
        }

        while(fast < s.size() && s[fast] != ' ')
        {
            s[slow++] = s[fast++];
        }
       }
       s.resize(slow);

    }
    string reverseWords(string s) {
        removeExtraSpace(s);

        reverse(s.begin(),s.end());   

        int slow = 0;
        for(int fast = 0; fast <= s.size(); fast++)
        {
            if(fast == s.size() || s[fast] == ' ')
            {
                reverse(s.begin()+slow,s.begin()+fast);
                slow = fast+1;
            }

        }
        return s;
    }
};

运行结果如下:

卡码网.55 右旋字符串:

55. 右旋字符串(第八期模拟笔试) (kamacoder.com)

没什么好说的,先整体逆置,在前k个逆置,最后剩余的逆置,代码如下:
 

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;

int main()
{
    int k = 0;
    string s;
    cin>>k;
    cin>>s;
    
    
    reverse(s.begin(),s.end());
    reverse(s.begin(),s.begin()+k);
    reverse(s.begin()+k,s.end());
    
    cout << s;
    return 0;
}

运行结果如下:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

起床写代码啦!

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

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

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

打赏作者

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

抵扣说明:

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

余额充值