代码随想录算法训练营 Day07 | 字符串 part01

344. 反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

cpp 复制代码
class Solution {
public:
    // 解法:对撞双指针
    void reverseString(vector<char>& s) {
        // 左指针指向头部,右指针指向尾部
        int l = 0, r = s.size() - 1;
        // 指针相遇则停止
        while(l < r){
            // 交换左右指针的字符,然后左指针右移、右指针左移
            swap(s[l++], s[r--]);
        }
    }
};

总结

1. 对撞双指针

从字符串两端向中间遍历,交换对应元素,是字符串 / 数组反转的标准写法。

2. 复杂度

时间复杂度:O(n)(仅遍历一半字符)

空间复杂度:O(1)(原地操作,无额外空间)

3 .关键函数

swap():C++ 内置交换函数,简洁高效。


541. 反转字符串 II

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

  • 如果剩余字符少于 k 个,则将剩余字符全部反转。
  • 如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
cpp 复制代码
class Solution {
public:
    // 剩余 < k 个:全部反转;剩余 k~2k:反转前k个
    string reverseStr(string s, int k) {
        // 步长为 2k,按组遍历字符串
        for(int i=0;i<s.size();i+=2*k){
            // 反转从 i 开始的 k 个字符
            // min 处理边界:剩余字符不足 k 个时,反转到字符串末尾
            reverse(s.begin()+i, min(s.begin()+i+k, s.end()));
        }
        return s;
    }
};

总结

1. 解题思路

2k 为一个步长遍历字符串,将字符串分成若干组;

每组只反转前 k 个字符;

剩余字符数 < k:全部反转

剩余字符数 k ≤ 数量 < 2k:只反转前 k 个

min(起始位置+k, 末尾) 一行代码完美处理所有边界

2. 关键知识点
  1. 库函数 reverse:左闭右开区间 [begin, end),直接反转指定区间,底层就是双指针实现;
  2. 时间复杂度:O(n) 每个字符仅被反转一次,线性遍历;
  3. 空间复杂度:O(1) 原地操作,无额外空间开销。

54. 替换数字(第八期模拟笔试)

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

cpp 复制代码
// 第一种写法:replace 库函数版
#include <iostream>
using namespace std;

int main(){
	string s;cin>>s;
	string mp="number";
	for(int i=0;i<s.size();i++){
		// 核心问题:替换后字符串变长,i会跳过字符!
		if(isdigit(s[i])) s.replace(i,1,mp);
	}
	cout<<s;
	return 0;
}

// 第二种写法:双指针从后往前原地修改
#include <iostream>
using namespace std;

int main(){
	string s;cin>>s;
	// 统计字符串中数字的个数
	int cnt=0;
    // 原字符串的最后一个字符下标
	int l=s.size()-1;
	for(int i=0;i<s.size();i++){
		if(isdigit(s[i])) cnt++;
	}
	// 扩容字符串:每个数字替换为number,长度增加5
	s.resize(s.size() + cnt*5);
	// 新字符串的最后一个字符下标
	int r=s.size()-1;
	// 核心:从后往前遍历(避免从前往后覆盖字符)
	while(l>=0){
		if(isdigit(s[l])){
			// 是数字:倒序填入 number
			s[r--]='r';
			s[r--]='e';
			s[r--]='b';
			s[r--]='m';
			s[r--]='u';
			s[r--]='n';
		}
		else{
			// 不是数字:直接复制到新位置
			s[r--]=s[l];
		}
		l--;
	}
	cout<<s;
	return 0;
}

总结

方法一
  • 致命 BUG:替换后字符串长度增加,字符后移,但循环变量 i 继续自增,会跳过下一个字符
  • 优点:代码极简,适合快速实现
  • 缺点:效率低,无法处理连续数字
方法二
  • 统计数字数量:计算替换后字符串的总长度
  • 预先扩容:避免频繁扩容导致效率降低
  • 双指针从后往前
    • 从前往后替换会覆盖未处理的字符
    • 从后往前替换,无覆盖、效率最高、原地修改
  • 倒序填充 number,完美匹配替换规则
相关推荐
residual_fan9 小时前
航空发动机故障诊断专用智能体(三):基于对比学习的时序特征区分方法
人工智能·算法·数据挖掘·数据分析
Logic10110 小时前
C语言/数据结构位运算题解:异或XOR找出数据表中的“独特编号“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
高亦真10 小时前
今天是学习嵌入式的第39天
linux·学习·算法
Omics Pro10 小时前
AI药物研发10原则!欧盟EMA×美国FDA
数据库·人工智能·算法·机器学习·自然语言处理
wabs66610 小时前
关于二叉树【力扣100.相同的树的思考】
数据结构·c++·算法·leetcode·二叉树·递归法
知知之之10 小时前
敏感数据查询:SHA-256 还是 HMAC-SHA256
算法
彧azz11 小时前
Java学习记录:判断语句
java·笔记·学习·算法
alphaTao11 小时前
LeetCode 每日一题 2026/9/14-2026/9/20
算法·leetcode
hanlin0311 小时前
刷题笔记:力扣第560题-和为k的子数组
笔记·算法·leetcode