字符串 - 代码随想录

字符串 - 代码随想录
Mr.L字符串
字符串刷题记录,基于代码随想录整理。
- 344 反转字符串(双指针)
- 541 反转字符串 II(分段处理)
- 模拟 替换数字(遍历构造)
- 151 反转字符串中的单词(去空格 + 整体反转 + 单词反转)
- 右旋 右旋字符串(整体反转)
- 28 找出字符串中第一个匹配项的下标(KMP)
- 459 重复的子字符串(KMP)
- 双指针:344、151
- 模拟分段处理:541、替换数字、右旋字符串
- KMP:28、459
344. 反转字符串
问题描述
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组
s的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用
O(1)的额外空间解决这一问题。
示例 1:
1 | 输入:s = ["h","e","l","l","o"] |
示例 2:
1 | 输入:s = ["H","a","n","n","a","h"] |
提示:
1 <= s.length <= 10^5s[i]都是 ASCII 码表中的可打印字符
思路
双指针:一个指向字符串头部,一个指向字符串尾部,同时向中间移动并交换字符。
代码
1 | class Solution { |
- 时间复杂度:
O(n) - 空间复杂度:
O(1)
541. 反转字符串 II
问题描述
给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符,再重新计数。
- 如果剩余字符少于
k个,则将剩余字符全部反转。 - 如果剩余字符小于
2k但大于或等于k个,则反转前k个字符,其余字符保持原样。
示例 1:
1 | 输入:s = "abcdefg", k = 2 |
示例 2:
1 | 输入:s = "abcd", k = 2 |
提示:
1 <= s.length <= 10^4s仅由小写英文组成1 <= k <= 10^4
思路
按题意每次处理长度为 2k 的一段,因此遍历时直接让下标每次跳 2 * k 即可。
- 若当前这一段剩余字符数不少于
k,就反转前k个字符。 - 若剩余字符数少于
k,就把剩余部分全部反转。
当需要固定规律一段一段处理字符串时,可以优先考虑在 for 循环的步长上做文章。
代码
1 | class Solution { |
- 时间复杂度:
O(n) - 空间复杂度:
O(1)
替换数字(第八期模拟笔试)
问题描述
给定一个字符串 s,它包含小写字母和数字字符,请编写一个函数,将字符串中的字母字符保持不变,而将每个数字字符替换为 number。
例如,对于输入字符串 "a1b2c3",函数应该将其转换为 "anumberbnumbercnumber"。
输入描述
输入一个字符串 s,s 仅包含小写字母和数字字符。
输出描述
打印一个新的字符串,其中每个数字字符都被替换为了 number。
输入示例
1 | a1b2c3 |
输出示例
1 | anumberbnumbercnumber |
提示信息
1 <= s.length < 10000
思路
遍历字符串,判断当前字符是否落在 '0' ~ '9' 范围内:
- 如果是数字,就向结果串追加
"number" - 否则直接追加原字符
代码
1 |
|
- 时间复杂度:
O(n) - 空间复杂度:
O(n)
151. 反转字符串中的单词
问题描述
给你一个字符串 s,请你反转字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
注意: 输入字符串 s 中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
示例 1:
1 | 输入:s = "the sky is blue" |
示例 2:
1 | 输入:s = " hello world " |
示例 3:
1 | 输入:s = "a good example" |
提示:
1 <= s.length <= 10^4s包含英文大小写字母、数字和空格' 's中 至少存在一个 单词
思路
这道题的核心是三步:
- 移除多余空格
- 反转整个字符串
- 再逐个反转每个单词
这样就能在保留单词内容的同时,把单词顺序整体翻转过来。
代码
1 | class Solution { |
- 时间复杂度:
O(n) - 空间复杂度:
O(1)
右旋字符串(第八期模拟笔试)
问题描述
字符串的右旋转操作是把字符串尾部的若干个字符转移到字符串的前面。给定一个字符串 s 和一个正整数 k,请编写一个函数,将字符串中的后面 k 个字符移到字符串的前面,实现字符串的右旋转操作。
例如,对于输入字符串 "abcdefg" 和整数 2,函数应该将其转换为 "fgabcde"。
输入描述
输入共包含两行,第一行为一个正整数 k,代表右旋转的位数。第二行为字符串 s,代表需要旋转的字符串。
输出描述
输出共一行,为进行了右旋转操作后的字符串。
输入示例
1 | 2 |
输出示例
1 | fgabcde |
提示信息
1 <= k < 100001 <= s.length < 10000
思路
这题有两种常见写法:
1. 复制字符串
把原串复制一份,形成 s + s,然后从 s.size() - k 位置开始连续取 s.size() 个字符。
2. 整体反转
右旋 k 位可以拆成三次反转:
- 整体反转
- 反转前
k个字符 - 反转后面的剩余字符
要注意先做 k %= s.size(),避免 k 大于字符串长度时越界。
代码
1 |
|
1 |
|
- 时间复杂度:
O(n) - 空间复杂度:复制字符串写法为
O(n),整体反转写法为O(1)
28. 找出字符串中第一个匹配项的下标
问题描述
给你两个字符串 haystack 和 needle,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1。
示例 1:
1 | 输入:haystack = "sadbutsad", needle = "sad" |
示例 2:
1 | 输入:haystack = "leetcode", needle = "leeto" |
提示:
1 <= haystack.length, needle.length <= 10^4haystack和needle仅由小写英文字符组成
思路
KMP 的核心思想:当出现字符串不匹配时,可以利用已经匹配过的信息,避免主串指针回退,从而提高匹配效率。
这里的关键就是 next 数组。
next[i]表示以下标i结尾的子串中,最长相等前后缀的长度。- 当匹配失败时,模式串指针
j可以直接跳到next[j - 1],继续比较。
什么是前缀和后缀?
- 前缀:不包含最后一个字符的、从第一个字符开始的连续子串
- 后缀:不包含第一个字符的、以最后一个字符结尾的连续子串
代码
1 | class Solution { |
- 时间复杂度:
O(n + m) - 空间复杂度:
O(m)
459. 重复的子字符串
问题描述
给定一个非空的字符串 s,检查是否可以通过由它的一个子串重复多次构成。
示例 1:
1 | 输入:s = "abab" |
示例 2:
1 | 输入:s = "aba" |
示例 3:
1 | 输入:s = "abcabcabcabc" |
思路
这题也可以用 KMP。
如果一个字符串 s 可以由某个更短的子串重复多次组成,那么 s 一定存在非零的最长相等前后缀。
设字符串长度为 n,next[n - 1] 表示整个字符串的最长相等前后缀长度:
- 若
next[n - 1] == 0,说明不存在可复用的重复结构。 - 若
next[n - 1] != 0,并且n % (n - next[n - 1]) == 0,说明字符串可以由长度为n - next[n - 1]的子串重复构成。
代码
1 | class Solution { |
- 时间复杂度:
O(n) - 空间复杂度:
O(n)
总结
双指针: 常用于原地反转、去空格等操作。
分段处理: 像 541 这类按固定长度处理字符串的问题,重点在循环步长。
整体反转: 右旋字符串、单词翻转都可以转化为多次反转。
KMP: 本质是利用已匹配信息加速失配后的跳转,核心在 next 数组定义与回退过程。
重复子串判断: 关键是把问题转化为最长相等前后缀。



