day8|C++|Leetcode|卡码网|字符串|344.反转字符|541.反转字符串 II|卡码网:54.替换数字|151.翻转字符串里的单词|卡码网:55.右旋转字符串

文章介绍了四种与字符串操作相关的LeetCode题目,包括反转字符串(344、541)、替换数字(54)、翻转单词(151)和右旋转字符串(55),主要运用双指针技巧和C++编程实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第四章 字符串 part01

Leetcode 344.反转字符串

链接344. 反转字符串

思路

双指针交换,在两端设置两个指针leftright,交换两指针位置处的数,之后left左移,right右移,之后再次交换,重复操作直到leftright交会。

完整C++代码如下

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

Leetcode 541.反转字符串 II

链接541. 反转字符串 II

思路

  1. 直观:算出len里有t个k,然后for循环t,每轮加2,如下图,思路很直接,i为奇数的k,直接用函数reverseString进行翻转,剩下部分判断后再单独拎出来做一次翻转。

    在这里插入图片描述

完整C++代码如下

class Solution {
public:
    string reverseStr(string s, int k) {
		int len=s.length();
        int t=len/k;
        for (int i = 0; i < t; i+=2){
            reverseString(s,i*k,(i+1)*k-1);  
        }
        if(t%2==0){
            reverseString(s,t*k,len-1);
        }
        return s;
    }
    void reverseString(string& s,int m,int n) {      
        for (int l = m, r = n ; l < r; ++l, --r) {
            swap(s[l], s[r]);
        }
    }
};

卡码网:54.替换数字

链接卡码网:54.替换数字

思路

双指针思维:将一个指针i设立在原字符串的末尾,j设立在替换数字结束后的字符串末尾,i先判断是否为数字,若不是,赋值给j处的字符,i,j前移继续判断;若是,j指针所处位置以及前5个位置设为number,j-=5;i,j前移,继续判断。

在这里插入图片描述

完整C++代码如下

#include <iostream>
using namespace std;
int main(){
    string s;
    cin >> s;
    int count = 0; // 统计数字的个数
    int sOldSize = s.size();
    for (int i = 0; i < s.size(); i++) {
        if (s[i] >= '0' && s[i] <= '9') {
            count++;
        }
    }
    //扩充s的大小,通过之前count计数的数字个数
    s.resize(s.size()+count *5);
    int sNewSize =s.size();
    //从前向后填充就是O(n^2)的算法了,因为每次添加元素都要将添加元素之后的所有元素整体向后移动。
    //可以品味一下此题解法和上题的不同,双指针的使用使得算法时间复杂度优化了
    for(int i=sOldSize-1,j=sNewSize-1;i<j;i--,j--){
        if(s[i] > '9' || s[i] < '0'){
            s[j]=s[i];
        }else{
            s[j]='r';
            s[j-1]='e';
            s[j-2]='b';
            s[j-3] = 'm';
            s[j-4] = 'u';
            s[j-5] = 'n';
            j -= 5;//-5是因为后面还要再-1
        }
    }
    cout<< s<<endl;
    
    
    
}

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

链接151. 反转字符串中的单词

思路

双指针:附加条件(空间复杂度O(1))

如下:我们要做的操作为

  • 将整个字符串多余空格全部删除
  • 将整个字符串翻转
  • 将每个单词翻转

完整C++代码如下

class Solution {
public:
    //作用:去除所有空格并在相邻单词之间添加空格
    void removeExtraSpaces(string& s) {
        int slow = 0;  
        for (int i = 0; i < s.size(); ++i) { 
            if (s[i] != ' ') { //遇到非空格就删除所有空格
                if (slow != 0) s[slow++] = ' '; //(这个是下面代码结束循环后的的下一轮)
                //既然删除了空格,就要再给单词之间添加一个空格 slow != 0说明不是第一个单词,需要在单词前添加空格
                while (i < s.size() && s[i] != ' ') { //补上该单词,遇到空格说明单词结束
                    s[slow++] = s[i++];
                }
            }
        }
        s.resize(slow); //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) {
        removeExtraSpaces(s); //去除多余空格,保证单词之间之只有一个空格
        reverse(s, 0, s.size() - 1);
        int start = 0; //removeExtraSpaces后保证第一个单词的开始下标一定是0
        for (int i = 0; i <= s.size(); ++i) {
            if (i == s.size() || s[i] == ' ') { //到达空格或者串尾,说明一个单词结束 进行翻转
                reverse(s, start, i - 1); //翻转,注意是左闭右闭的翻转
                start = i + 1; //更新下一个单词的开始下标start
            }
        }
        return s;
    }
}

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

链接55.右旋转字符串

思路

  1. 直观法

  2. 两次翻转思路:

    • 首先,将整个字符串 s 进行反转,即字符串倒置。
    • 然后,将前 n 个字符进行反转,使得前 n 个字符逆序排列。
    • 接着,将剩余的字符进行反转,使得剩余字符逆序排列。

完整C++代码如下


int main() {
    string s;
    int k;
    cin >> k;
    cin >> s;
    
    // 将s末尾的k个字符移到开头
    string t = s.substr(s.length() - k, k) + s;

    // 删除字符串t末尾的k个字符
    t.erase(t.length() - k, k);
    
    cout << t;
    
    return 0;
}

#include<iostream>
#include<algorithm>
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;

} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值