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

文章目录

  • 1.反转字符串
  • 2.反转字符串II
  • 3.替换数字
  • 4.翻转字符串里的单词
  • 5.右旋转字符串


1.反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

示例 1:
输入: s = ["h","e","l","l","o"]
输出: ["o","l","l","e","h"]

示例 2:
输入: s = ["H","a","n","n","a","h"]
输出: ["h","a","n","n","a","H"]

提示:

  • 1 <= s.length <= 10^5
  • s[i] 都是 ASCII 码表中的可打印字符

字符串基础题目,双指针方法,两个指针同时向中间移动,并交换元素。代码如下:

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

    }
};

2.反转字符串II

给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。

  • 如果剩余字符少于 k 个,则将剩余字符全部反转。
  • 如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。

示例 1:
输入: s = "abcdefg", k = 2
输出: "bacdfeg"

示例 2:
输入: s = "abcd", k = 2
输出: "bacd"

提示

  • 1 <= s.length <= 10^4
  • s 仅由小写英文组成
  • 1 <= k <= 10^4

让i 每次移动 2 * 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.end());
            }
        }
        return s;
    }
};

3.替换数字

给定一个字符串 s,它包含小写字母和数字字符。编写一个函数,将字符串中的字母字符保持不变,而将每个数字字符替换为number。例如,对于输入字符串 "a1b2c3",函数应该将其转换为 "anumberbnumbercnumber"

输入一个字符串 ss 仅包含小写字母和数字字符。

打印一个新的字符串,其中每个数字字符都被替换为了number

输入示例
a1b2c3
输出示例
anumberbnumbercnumber
提示
数据范围:
1 <= s.length < 10000

使用空间复杂度为O(1)的方法实现,可以先扩充数组到替换后的长度,然后利用双指针方法从尾部依次添加字符。很多数组填充类的问题,其做法都是先预先给数组扩容带填充后的大小,然后在从后向前进行操作。代码如下:

#include 
using namespace std;
int main(){
    string s;

    while(cin >> s){//读取字符串
        int count = 0;
        for(int i = 0; i < s.size(); i++) {//计算数字数量
            if(s[i] >= '0' && s[i] <= '9') {
                count++;
            }
        }
        int old_size = s.size();

        s.resize(s.size() + count * 5);
        int new_size = s.size();
        for(int i = old_size - 1, j = new_size - 1; i >= 0 ;i--) {//双指针
            if(s[i] >= '0' && s[i] <= '9') {
                s[j--] = 'r';
                s[j--] = 'e';
                s[j--] = 'b';
                s[j--] = 'm';
                s[j--] = 'u';
                s[j--] = 'n';
            }
            else {
                s[j--] = s[i];
            }
        }
        cout << s << endl;
    }
}

4.翻转字符串里的单词

给你一个字符串 s,请你反转字符串中单词的顺序。

单词是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的单词分隔开。

返回单词顺序颠倒且单词之间用单个空格连接的结果字符串。

注意:输入字符串 s 中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

示例 1:
输入: s = "the sky is blue"
输出: "blue is sky the"

示例 2:
输入: s = " hello world "
输出: "world hello"
解释: 反转后的字符串中不能存在前导空格和尾随空格。

示例 3:
输入: s = "a good example"
输出: "example good a"
解释: 如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。

提示

  • 1 <= s.length <= 10^4
  • s 包含英文大小写字母、数字和空格 ' '
  • s 中至少存在一个单词

进阶
如果字符串在你使用的编程语言中是一种可变数据类型,请尝试使用 O(1) 额外空间复杂度的原地解法。

分为三步:去掉多余空格、将整个字符串反转、将每个单词反转
去掉多余空格使用快慢双指针方法;
反转字符串使用前后双指针,从两边向中间移动反转。

class Solution {
public:
    void removeExtraSpaces(string &s) {//双指针去掉多余空格
        int slow = 0;//快慢指针
        int fast = 0;
        while(s.size() > 0 && fast < s.size() && s[fast] == ' '){//去掉头部空格
            fast++;
        }
        for(;fast < s.size(); fast++) {//去掉字母间多余空格
            if(fast-1 > 0 && s[fast] == s[fast-1] && s[fast] == ' ') {
                continue;
            }
            else {
                s[slow++] = s[fast];
            }
        }
        if(slow -1 > 0 && s[slow - 1] == ' ') {//去掉尾部空格
            slow--;
        }
        s.resize(slow);
    }
    void reverse(string &s, int start, int end) {//双指针反转
        for(int i = start, j = end; i < j; i++, j--) {
            swap(s[i], s[j]);
        }
    }
    string reverseWords(string s) {
        int SpacesIndex = 0;//每个单词反转一次
        removeExtraSpaces(s);
        reverse(s,0,s.size() - 1);
        for(int i = 0; i <= s.size(); i++) {
            if(s[i] == ' ' || i == s.size()) {//遇到空格和到末尾 进行反转单词
                reverse(s,SpacesIndex, i-1);
                SpacesIndex = i + 1;
            }
        }
        return s;
    }
};

5.右旋转字符串

字符串的右旋转操作是把字符串尾部的若干个字符转移到字符串的前面。给定一个字符串 s 和一个正整数 k,请编写一个函数,将字符串中的后面 k 个字符移到字符串的前面,实现字符串的右旋转操作。

例如,对于输入字符串 "abcdefg" 和整数 2,函数应该将其转换为 "fgabcde"

输入共包含两行,第一行为一个正整数 k,代表右旋转的位数。第二行为字符串 s,代表需要旋转的字符串。

输出共一行,为进行了右旋转操作后的字符串。

输入示例
2
abcdefg
输出示例
fgabcde

提示

  • 1 <= k < 10000
  • 1 <= s.length < 10000

字符串处理常用方法,先整体反转,后局部反转。代码如下:

#include
#include
using namespace std;
int main() {
    int n;
    string s;
    cin >> n;
    cin >> s;
    int len = s.size(); //获取长度

    reverse(s.begin(), s.end()); // 整体反转
    reverse(s.begin(), s.begin() + n); // 先反转前一段,长度n
    reverse(s.begin() + n, s.end()); // 再反转后一段

    cout << s << endl;

} 

你可能感兴趣的:(算法记录,算法)