题目:
给定一个字符串 s 和一个整数 k,从字符串开头算起, 每计数至 2k 个字符,就反转这 2k 个字符中的前 k 个字符。
如果剩余字符少于 k 个,则将剩余字符全部反转。
如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
示例:
输入: s = "abcdefg", k = 2
输出: "bacdfeg"
题目意图解析:
题目要求按照给定的步骤修改输入的字符串 s,具体步骤和规则如下:
-
字符串分块处理: 将字符串
s按照长度2k进行分块。每块长度最多为2k,按这种方式划分,字符串会被分成若干块。 -
每块内的操作: 对于每一块:
- 如果块的长度等于
2k,则反转这个块中的前k个字符。 - 如果块的长度少于
2k但大于或等于k,则仅反转这个块中的前k个字符,剩下的字符保持不变。 - 如果块的长度少于
k,则将这个块中的所有字符全部反转。
- 如果块的长度等于
-
结果连接: 处理完所有块之后,将每块处理后的结果连接起来,形成最终的字符串。
以题目中的示例来说明:
- 输入字符串
s = "abcdefg",k = 2。 - 将字符串分为
2k = 4个字符一组,得到 "abcd" 和 "efg" 两组。 - 对 "abcd" 中的前
k = 2个字符进行反转,得到 "bacd"。 - 对 "efg",因为长度小于
2k但大于k,也反转前k = 2个字符,得到 "fecg"。 - 连接处理后的两块结果 "bacd" 和 "fecg",得到最终输出 "bacdfeg"。
class Solution:def reverseStr(self, s: str, k: int) -> str:# 定义一个反转字符串函数def reverse_substring(text):left, right = 0, len(text) - 1while left < right:# 分别交换左右指针所指的值text[left], text[right] = text[right], text[left]left += 1right -= 1return text# 将输入的字符串s转化成列表resres = list(s)# 遍历列表resfor cur in range(0, len(s), 2 * k):res[cur: cur + k] = reverse_substring(res[cur : cur + k])return ''.join(res)
上述代码实现解答:
1. 定义 reverse_substring 辅助函数
这个函数用于反转给定的字符串片段。具体步骤如下:
- 接收一个字符串片段
text作为参数。 - 初始化两个指针
left和right,分别指向字符串的开始和结束位置。 - 使用
while循环,当left小于right时执行循环体:- 交换
left和right指针所指向的字符。 - 将
left指针向右移动一位。 - 将
right指针向左移动一位。
- 交换
- 当
left不再小于right时,循环结束,此时字符串片段已被反转。 - 返回修改后的字符串片段。
这个函数是处理字符串反转的核心逻辑,它直接在传入的列表片段上进行修改,由于列表是可变数据类型,这种修改是原地进行的。
2. reverseStr 方法
这个方法用来控制整个字符串的反转流程:
- 将输入的字符串
s转换成列表res。这是因为字符串在 Python 中是不可变的,而列表允许我们进行原地修改。 - 使用
for循环遍历res,步长为2k,这意味着每次迭代跳过2k个字符。cur是当前迭代的起始索引。- 在每次循环中,
res[cur: cur + k]选取从cur开始的k个字符。 - 这个子列表通过
reverse_substring函数进行反转。 - 反转结果赋值回
res的相应位置,由于是列表,所以这个操作修改了res的实际内容。
- 在每次循环中,
- 完成所有迭代后,所有需要反转的部分已经在
res中被正确反转。 - 使用
join函数将列表res转换回字符串,并返回这个字符串。
实际应用
假设 s = "abcdefg",k = 2。流程如下:
- 将
s转为列表:res = ['a', 'b', 'c', 'd', 'e', 'f', 'g'] - 循环迭代:每次处理
2k = 4个字符。- 第一次迭代:
cur = 0,处理res[0:2]->['a', 'b']反转为['b', 'a'] - 第二次迭代:
cur = 4,处理res[4:6]->['e', 'f']反转为['f', 'e']
- 第一次迭代:
- 最终列表:
res = ['b', 'a', 'c', 'd', 'f', 'e', 'g'] - 转换回字符串并返回:"bacdfeg"
上述过程逐步应用了字符串分块和反转的逻辑,实现了每隔 2k 字符的交替反转效果。
重难点代码解析:
for cur in range(0, len(s), 2 * k):
这行代码中的 for 循环是用来迭代整个字符串 s,采用了特定的步长来确保每次迭代可以正确地按照指定的模式处理字符串。
range 函数的三个参数:
- 第一个参数
0:这是range函数的起始值,表示循环将从索引0开始,也就是字符串的第一个字符。 - 第二个参数
len(s):这是range函数的结束值,len(s)表示字符串s的长度,这样确保循环覆盖整个字符串,但不包括len(s)本身,因为range是半开区间 [start, end)。 - 第三个参数
2 * k:这是range函数的步长,决定了每次循环增加的索引数量。这里的2 * k表示每次迭代跳过2k个字符。这个设置是因为题目中的操作模式是:对每2k字符的前k字符进行反转,而后k字符保持原样。因此,每次处理后跳过2k个字符到下一个待处理区间的开始。
循环的操作逻辑:
循环结构使得每次循环都从序列的 cur 位置开始,处理长度为 k 的子序列进行反转(如果 cur + k 超过字符串长度,那么只处理从 cur 开始到字符串结束的部分)。
例子演示:
假设 s = "abcdefghijk",k = 3:
- 第一次循环:
cur = 0,处理区间是[0:3](即 "abc")。 - 第二次循环:
cur = 6,处理区间是[6:9](即 "ghi")。
在每个循环迭代中,cur 指向的是每个 2k 区间的开始位置,这样设计循环是为了实现题目要求的每 2k 个字符中的前 k 个字符反转的功能。
res[cur: cur + k] = reverse_substring(res[cur: cur + k])
这句代码是实现字符串反转的核心部分,在整体 for 循环中的每次迭代里执行,具体地处理字符串中的特定子序列,可以分解这行代码为几个关键操作:
1. res[cur: cur + k]
这部分是一个列表切片操作,用于从列表 res 中选取从索引 cur 开始到 cur + k 的元素。这个切片包括从 cur 到 cur + k - 1 的所有元素,总共 k 个字符(如果存在的话;如果 cur + k 超出了列表的长度,它会简单地取到列表末尾)。这是要被反转的子字符串。
2. reverse_substring(res[cur: cur + k])
这个调用将上面提到的切片作为参数传递给 reverse_substring 函数。如前所述,reverse_substring 函数是一个翻转其输入的函数,并返回翻转后的列表(或子列表)。
3. res[cur: cur + k] = ...
这部分是赋值操作。函数 reverse_substring 返回的翻转后的列表将替换原来 res 列表中 cur 到 cur + k 的部分。这是一个原地修改,意味着 res 列表在这一操作后更新了其中的一段。
功能和作用
整个操作的作用是在列表 res 中的指定位置原地翻转 k 长度的子列表。这实现了题目要求的在每隔 2k 字符的区间内反转前 k 个字符的功能。这种方法利用了 Python 列表的可变性,通过原地修改来避免额外的内存分配,提高效率。
示例解析
假设 s = "abcdefghi",k = 3,经过 res = list(s) 后,res 将是 ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']。
- 在循环的第一次迭代(
cur = 0),res[0:3]为['a', 'b', 'c']。经过reverse_substring处理后,这部分变为['c', 'b', 'a'],并被重新赋值给res[0:3],使得res变为['c', 'b', 'a', 'd', 'e', 'f', 'g', 'h', 'i']。 - 接下来的迭代会处理更远的区间,如
cur = 6,针对['g', 'h', 'i']等部分。
通过这样的操作,代码有效地在给定间隔内反转字符串的指定部分,同时保持其他部分不变。
综上,本文的对于力扣541. 反转字符串 II的Python3解答,仅仅是个人学习资料记录,也十分高兴我的见解可以帮助其他的正在做这个题目的同学,基础较差,仅仅是个人见解,大神勿喷,欢迎交流,谢谢!