代码随想录训练营第八天|344. 反转字符串、541. 反转字符串 II、 卡码网:54.替换数字

一、反转字符串

题目链接/文章讲解/视频讲解: 代码随想录

1.和链表反转一样,双指针法(用于同时操作两个元素)

2.左右指针,相互交换直到中间,也可以用while(left<right)

代码:

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

二、反转字符串Ⅱ

题目链接/文章讲解/视频讲解:代码随想录

1.重点:代码技巧,逻辑

2.代码随想录里是:以2*k的步长遍历数组,条件一和条件二是差不多的,都是反转k个元素

首先判断距离数组结尾是否还有多长距离,如果还有k个则反转k个,continue跳出此次循环,不足则反转剩余的全部。

3.自己采用的是计数,然后三个条件判断。

        for (int i = 0; i < s.size(); i += (2 * k)) {
            // 1. 每隔 2k 个字符的前 k 个字符进行反转
            // 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
            if (i + k <= s.size()) {
                reverse(s, i, i + k - 1);
                continue;
            }
            // 3. 剩余字符少于 k 个,则将剩余字符全部反转。
            reverse(s, i, s.size() - 1);
        }
        return s;
    }

代码:

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]);
        }
    }
    string reverseStr(string s, int k) {
        for (int i = 0; i < s.size(); i += (2 * k)) {
            // 1. 每隔 2k 个字符的前 k 个字符进行反转
            // 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
            if (i + k <= s.size()) {
                reverse(s, i, i + k - 1);
                continue;
            }
            // 3. 剩余字符少于 k 个,则将剩余字符全部反转。
            reverse(s, i, s.size() - 1);
        }
        return s;
    }
};
class Solution {
public:
    void reversedata(string &s,int left,int right)
    {
        for(;left<right;left++,right--)
        {
            swap(s[left],s[right]);
        }
    }

    string reverseStr(string s, int k) 
    {
        int count=s.size();
        int left=0;
        while(count)
        {
            if(count>=2*k)
            {
            reversedata(s,left,left+k-1);
            count-=2*k;
            left+=2*k;
            }
            else if(count>=k&&count<2*k)
            {
            reversedata(s,left,left+k-1);
            count=0;
            }
            else{
            reversedata(s,left,s.size()-1);
            count=0;
            }
        }
       return s;
    }
};

三、替换数字

题目链接/文章讲解: 代码随想录

1.一开始想的是从前向后填充

从前向后填充就是O(n^2)的算法,每次添加元素都要将添加元素之后的所有元素整体向后移动。

2.其实很多数组填充类的问题,其做法都是先预先给数组扩容带填充后的大小,然后在从后向前进行操作。

对于线性数据结构,填充或者删除,后序处理会高效的多。

①不用申请新数组。②从后向前填充元素,避免了从前向后填充元素时,每次添加元素都要将添加元素之后的所有元素向后移动的问题。

3.双指针法,一个遍历,一个填充,经典用法

#include<iostream>
using namespace std;

int main()
{
    string s;
    while (cin >> s)
    {
        int old=s.size()-1;//旧的数组的末端元素下标
        int count=0;
        //统计字母的个数
        for(int i=0;i<s.size();i++)
        {
            if(s[i]>='0'&&s[i]<='9')
            {
                count++;
            }
        }
        s.resize(s.size()+count*5);//number 六位,原本有一个位置了,所以只要加 5
        //定义一个新指针,用于填充
        int newindex=s.size()-1;
        //注意循环结束时old等于0,0处可能出现数字,也需要填充
        while(old>=0)
        {
            if(s[old]>='0'&&s[old]<='9')
            {
                s[newindex--]='r';
                s[newindex--]='e';
                s[newindex--]='b';
                s[newindex--]='m';
                s[newindex--]='u';
                s[newindex--]='n';
            }
            else
            {
                s[newindex]=s[old];
                newindex--;
            }
            old--;
        }
              cout << s << endl;      
        
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值