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

LeetCode 344.反转字符串

题目链接:344.反转字符串

踩坑:无坑可踩

思路:和反转数组是一模一样的,相向双指针。

代码:

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

LeetCode 541.反转字符串||

题目链接:541.反转字符串||

踩坑:无坑可踩

思路:使用一个指针指向每次需要操作的区间的头部,再指定一个指针距离头指针k个距离,此时便可以进行字符串反转。理解344后这个题就没什么难点了。

代码:

class Solution {
public:
    string reverseStr(string s, int k) {
        int left = 0;
        int right = 0;
        for(int i = 0; i * 2 * k < s.length(); i++)
        {
            left = i * 2 * k;
            right = left + k - 1;
            if(right > s.length()-1) right = s.length() - 1;
            while(left < right)
            {
                char t = s[left];
                s[left] = s[right];
                s[right] = t;
                left++;
                right--;
            }
        }
        return s;
    }
};

卡码网:54.替换数字

题目链接:54.替换数字

踩坑:string类型有很多方便的接口,要尽量熟悉

思路:

  1. 我自己的思路:遍历字符串,遇到数字字符后,提取指针之后的字串,提取指针之后的字串,字符串=前字串+“number”+后字串
  2. 卡哥的思路:遍历字符串,得到数字字符的个数,以此拓展原字符串的大小。双指针一个left在原字符串尾部,一个right在完整字符串尾部。从后向前遍历原字符串,如果不是数字字符则移到right,如果是数字字符则从right开始反向填充“number”。

代码:

// 我自己的思路
#include <iostream>
#include <string>

using namespace std;

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

LeetCode 151.翻转字符串里的单词

题目链接:151.翻转字符串里的单词

踩坑:这是一道非常需要耐心仔细的题。在删除多余空格的时候要考虑最开始不需要空格,在快指针循环寻找字母字符时要注意循环判断小于字符串长度(否则会越界),删除完毕之后还要resize。在定位需要反转的单词时,依然是要注意快指针在结束前反转最后一个单词。

思路:

  1. 删除多余空格:借鉴“移除数组元素”,快指针寻找新数组的元素(非空格),慢指针指向要填入的位置。至于两个单词间的空格,可以选择在填入单词后填入,也可以在填入单词前填入。这里选择在之前填入(较为简单,只需要判断慢指针是否是0)
  2. 反转单词:相向双指针
  3. 总体:先删除多余空格,再将整个字符串反转,再遍历锁定空格位置来反转每一个单词。

代码:

class Solution {
public:
    void removeBlock(string& s) {
        int slow = 0;
        for(int i = 0; i < s.length(); i++)
        {
            if(s[i] != ' ')
            {
                if(slow != 0) s[slow++] = ' ';
                while(i < s.length() && s[i] != ' ')
                {
                    s[slow++] = s[i++];
                } 
            }
        }
        s.resize(slow);
    }
    void reverse(string& s, int start, int end)
    {
        int left = start;
        int right = end;
        while(left < right)
        {
            char t = s[left];
            s[left] = s[right];
            s[right] = t;
            left++;
            right--;
        }
    }
    string reverseWords(string s) {
        removeBlock(s);
        reverse(s, 0, s.length()-1);
        int start = 0;
        for(int i = 0; i <= s.length(); i++)
        {
            if(s[i] == ' ' || i == s.length())
            {
                reverse(s, start, i-1);
                start = i+1;
            }
        }
        return s;
    }
};

卡码网 55.右旋转字符串

题目链接:55.右旋转字符串

踩坑:没有领悟到全局反转,局部反转的精髓,使用了申请新空间的办法。

思路:

  1. 我自己的思路:可以认为这样的字符串是首尾相接的,是一个圈。那么每一个位置后移k位通过对圈的长度取余就可以得到新的位置。
  2. 卡哥的思路:卡哥还是这么喜欢给我们上难度,不过确实是有利于我们反思各种方法。这里的核心还是全局反转配合局部反转可以得到字符串中的相对翻转。先对全局进行反转,再对前k个进行反转,后len-k个进行反转即可。

代码:

// 我自己的思路
#include <iostream>
#include <string>

using namespace std;
int main()
{
    string s;
    int k;
    cin>> k >> s;
    char result[s.length()];
    for(int i = 0; i < s.length(); i++)
    {
        result[(i+k)%s.length()] = s[i];
    }
    for(int i = 0; i < s.length(); i++)
    {
        cout<<result[i];
    }
    return 0;
}
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值