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

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

  • 反转字符串
  • 541. 反转字符串II
  • 卡码网:54.替换数字
  • 151.翻转字符串里的单词
  • 卡码网:55.右旋转字符串

本文的思路和代码大部分来自:

1.《代码随想录》:https://programmercarl.com/0541.%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2II.html#%E6%80%9D%E8%B7%AF
2. y总的acwing:https://www.acwing.com

反转字符串

我是一看就会,一写就废同学,先看代码:

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

还有:

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

这道题目的思路是双指针,代码很简洁,我就不过多叙述了

541. 反转字符串II

看代码:

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

这道题目的代码是y总的,相比之下其实我更加倾向《代码随想录》的代码,更加明了易懂,这里我描述一下思路。
首先是将一个字符串以2k为界分段,在每一段中,把前k个字符串进行反转,字符串本身不足k,肯定要全部翻转,字符串本身大于k但是小于2k,就把前k个翻转即可。
然后对i每2k就进行一次左右端点赋值,左端点比较好说就是i,但是右端点就需要分情况,因为当处理到最后一段的时候就会有问题,如果最后一段的长度大于k,那就翻转前k个,如果最后一段的长度小于k,也就是i+k

卡码网:54.替换数字

先看代码:

#include
#include
#include
using namespace std;
int main()
{
    string s;
    int count = 0;
    int OldSize,NewSize;
    cin >> s;
    for(int i = 0;i < s.size();i++)
    {
        if(s[i] >= '0' && s[i] <= '9')
        {
            count++;
        }
    }
    OldSize = s.size();
    s.resize(OldSize + count * 5);
    NewSize = s.size();
    for(int i = NewSize - 1,j = OldSize - 1;j < i;i--,j--)
    {
        if(s[j] < '0' || s[j] > '9')
        {
            s[i] = s[j];
        }
        else
        {
            s[i] = 'r';
            s[i - 1] = 'e';
            s[i - 2] = 'b';
            s[i - 3] = 'm';
            s[i - 4] = 'u';
            s[i - 5] = 'n';
            i -= 5;
        }
    }
    cout << s << endl;
    return 0;
}

这道题目《代码随想录》的思路非常清晰,图文并茂,请参考。

https://programmercarl.com/kama54.%E6%9B%BF%E6%8D%A2%E6%95%B0%E5%AD%97.html#%E6%80%9D%E8%B7%AF

我这里说一下代码方面需要注意的吧,首先count变量是记录数字的,所以一定是s[i] >= ‘0’ && s[i] <= ‘9’,这里的需要注意等号,这也是我在给自己提醒,因为我就是把等号忘记了。因此后面s[j] < ‘0’ || s[j] > '9’自然就不需要等号,最后插入number后忘记把i往前移5。至于为什么是5不是6,看卡哥的解释就都明白了。

151.翻转字符串里的单词

先看代码:

class Solution {
public:
    string reverseWords(string s) {
        int k = 0;
        for(int i = 0;i < s.size();)
        {
            int j = i;
            while(j < s.size() && s[j] == ' ') j++;
            if(j >= s.size()) break;
            i = j;
            while(j < s.size() && s[j] != ' ') j++;
            reverse(s.begin() + i,s.begin() + j);
            if(k) s[k++] = ' ';
            while(i < j) s[k++] = s[i++];
        }
        s.erase(s.begin()+k,s.end());
        reverse(s.begin(),s.end());
        return s;
    }
};

这道题目我从我老师y总那里学到两个思路,(以"The sky is blue"为例):

  1. 可以先整体翻转:eulb si yks ehT,然后再每个单词每个单词的翻转,得到:blue is sky The。
  2. 第二种方法就是先翻转每个单词,然后整体翻转:ehT yks si eulb,然后再整体翻转:blue is sky The。
    回到这个题目上,用的是第二种方法,其实比较棘手的是空格,这里定了i,j,k,这里i的作用就是用于指向每个单词的头部,j的作用就是指向每个单词的尾部,以方便翻转,而k的作用就是保证除了每个单词之间的空格之外,没有其他的空格。
    这里先让i,j,k在同一个起点,先让j开始跑起来,遇到空格就跳过,直到遇到第一个不是空格的地方,让i和j指到同一个地方(也就是单词的头部),然后j继续往后走,遇到第一个空格停下,这里就是这个单词的尾部,最后翻转reverse(s.begin()+i,s.begin()+j); 这个时候k还在开头等着呢,而且k是整个字符串的开头,因此前面不用加’ ',但是单词开头i和字符串开头k之间还可能右空格,于是把i到j整体移过去,就是while(i < j) s[k++] = s[i++]; 这里while里面的条件就是保证不能超过这个单词,万一后面空格也移过去就麻烦了。
    每个单词翻转完了,第一步也就结束了,这时开始第二部,整体翻转,但是,在这之前,还要把整个字符串后面的空格清一清,所以直接删除k之后的字符串就行了。然后整体翻转。

卡码网:55.右旋转字符串

看代码:

#include
#include
#include
using namespace std;

int n;
string s;

int main()
{
    cin >> n;
    cin >> s;
    int i = 0;
    while(i < (s.size() - n)) i++;
    reverse(s.begin(),s.begin() + i);
    reverse(s.begin() + i,s.end());
    reverse(s.begin(),s.end());
    cout << s << endl;
    return 0;
}

这道题和上一个题很像,而且比上一题还少了烦人的空格。直接以s.size()-n为界,先进行各自部分翻转再整体翻转,或者是先整体再各部分,这里我是先各部分再整体。

你可能感兴趣的:(算法,数据结构,leetcode)