代码随想录算法训练营 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,完美匹配替换规则
相关推荐
yi0113 小时前
LeetCode 15:三数之和|排序 + 双指针,如何避免重复答案?
笔记·python·算法·leetcode·双指针
-dzk-3 小时前
【多维动态规划】LC 1143.最长公共子序列
算法·动态规划
C++ 老炮儿的技术栈3 小时前
char (*csConnectName)[256]; 和 char csConnectName [256] 有什么区别
java·c语言·开发语言·c++·人工智能·算法·c
Omics Pro3 小时前
全新可重分析!代谢组质谱专用
数据库·人工智能·算法·机器学习·自然语言处理
Nebula_g3 小时前
JavaSE加强:线程Thread(线程安全重点)
java·开发语言·jvm·算法·javase·技术栈
一只废狗狗狗狗狗狗狗狗狗3 小时前
Network架构1——卷积神经网络CNN
人工智能·算法·cnn
是希燃亚3 小时前
AI Agent 的未来,可能不是更强,而是更简单
算法·架构
alphaTao3 小时前
LeetCode 每日一题 2026/10/5-2026/10/11
算法·leetcode
liliangcsdn3 小时前
现金流指标的探索和分析
大数据·算法
wang09074 小时前
硬着头皮学数据结构和算法之Myers算法
数据结构·算法