代码随想录算法训练营 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,完美匹配替换规则
相关推荐
土司大王5 小时前
LeetCode hot100——对称二叉树
算法·leetcode·职场和发展
sali-tec6 小时前
C# 基于OpenCv的视觉工作流-章106-差值追踪
图像处理·人工智能·opencv·算法·计算机视觉
Navigator_Z6 小时前
LeetCode //C - 1208. Get Equal Substrings Within Budget
c语言·算法·leetcode
手写码匠6 小时前
Dify 多 Agent 工具权限与安全沙箱实战:让智能体“有能力,但不越权“
人工智能·深度学习·算法·aigc
黎阳之光6 小时前
打破堆场感知黑盒:黎阳之光视频孪生,构建港口码头网格化透明管控新体系
大数据·人工智能·算法·安全·数字孪生
大模型码小白7 小时前
AI 对话流性能调优:万级消息的虚拟滚动落地
java·大数据·前端·javascript·人工智能·算法·机器学习
sel_97 小时前
【多轮对话论文导读(三)】多轮对话与Agent论文阅读笔记:用户模拟、轨迹生成与长期记忆
论文阅读·人工智能·笔记·深度学习·算法·机器学习
Asize8 小时前
438. 找到字符串中所有字母异位词
算法
Asize8 小时前
283. 移动零
算法
船厂电气自动化ai大模型10 小时前
AI大模型与数学·第57课 傅里叶全套工具链综合实战:串联级数/连续变换/DFT/FFT,图像、音频、扩散模型完整例题
数据结构·人工智能·深度学习·算法·机器学习