
题目考点
这道题主要考这几个点:
- 字符串切片
- 循环分组处理
- 去重,但要保留原来的先后顺序
- 函数题的输出方式
这题表面看起来像“字符串题”,但真正的核心是:
把一个大字符串按长度 k 分段,然后对每一段做“按出现顺序去重”。
审题
先把题目翻译成人话。
已知:
- 一个字符串
string - 一个整数
k
题目保证:
- 字符串长度
n一定是k的倍数
所以我们可以把整个字符串平均切成 n / k 段,每段长度都正好是 k。
然后对每一段做这样的处理:
- 从左到右看字符
- 如果这个字符之前没出现过,就保留
- 如果这个字符之前已经出现过,就跳过
最后把每一段处理后的结果,各打印一行。
思路提示
先不要急着写代码,先把思路抓住。
你可以把整道题拆成两个问题:
第一步:怎么把字符串按 k 个一组切开?
比如:
string = "AABCAAADA"
k = 3
那么它会被切成:
"AAB""CAA""ADA"
也就是说,每次取连续 k 个字符。
这通常可以用步长为 k 的循环做到。
第二步:怎么把每一组“去重但保留顺序”?
比如 "AAB":
- 先看
A,没出现过,保留 - 再看
A,出现过了,跳过 - 再看
B,没出现过,保留
结果就是 "AB"
这里要特别注意:
不是普通去重,而是“保留第一次出现的顺序”。
所以不能直接写:
set("AAB")
因为集合虽然能去重,但不保证原来的顺序。
完整设计思路
现在把完整步骤整理出来。
第 1 步:每次取一段长度为 k 的子串
可以让下标每次跳 k:
- 第一次取
string[0:3] - 第二次取
string[3:6] - 第三次取
string[6:9]
也就是:
for i in range(0, len(string), k):
然后当前这一段就是:
part = string[i:i+k]
第 2 步:对当前这段做“按顺序去重”
准备两个东西:
seen:记录哪些字符已经出现过了result:保存最后要输出的字符串
然后从左到右遍历 part 中的每个字符:
- 如果字符不在
seen里,说明第一次出现- 加入
result - 加入
seen
- 加入
- 如果已经在
seen里,就跳过
第 3 步:处理完一段,就打印一行
因为题目要求的是“每个结果单独打印一行”,所以每一段处理完直接 print(result) 即可。
代码实现
下面是适合初学者的写法:
def merge_the_tools(string, k):
for i in range(0, len(string), k):
part = string[i:i + k]
seen = set()
result = ""
for ch in part:
if ch not in seen:
seen.add(ch)
result += ch
print(result)
如果题目平台给了输入模板,通常完整写法会是这样:
def merge_the_tools(string, k):
for i in range(0, len(string), k):
part = string[i:i + k]
seen = set()
result = ""
for ch in part:
if ch not in seen:
seen.add(ch)
result += ch
print(result)
if __name__ == '__main__':
string = input()
k = int(input())
merge_the_tools(string, k)
运行演示
我们用题目的样例来手动走一遍。
输入:
string = "AABCAAADA"
k = 3
第一轮
取出:
part = "AAB"
开始遍历:
- 看
A,seen里没有result = "A"seen = {"A"} - 再看
A,已经在seen里
跳过 - 看
B,seen里没有result = "AB"seen = {"A", "B"}
输出:
AB
第二轮
取出:
part = "CAA"
开始遍历:
- 看
C,第一次出现result = "C" - 看
A,第一次出现result = "CA" - 再看
A,重复
跳过
输出:
CA
第三轮
取出:
part = "ADA"
开始遍历:
- 看
A,第一次出现result = "A" - 看
D,第一次出现result = "AD" - 再看
A,重复
跳过
输出:
AD
最终输出
AB
CA
AD
这题最容易卡住的地方
这题初学者最容易卡在两个地方。
1. 为什么不能直接用 set(part)?
因为 set 只能帮你去重,但它不会帮你保留原字符串中的顺序。
而这题要求的是:
保留第一次出现时的顺序。
比如:
part = "AAB"
你想要的是:
"AB"
但如果直接做:
set(part)
你得到的是一个集合,不是按原顺序排好的字符串。
所以这题必须自己从左到右扫描。
2. 为什么要分段处理,而不是对整个字符串一次去重?
因为题目不是让你对整个字符串去重,而是:
每 k 个字符作为一个小组,每组单独处理。
比如:
"AABCAAADA"
不是直接变成 "ABCD",而是要先切成:
"AAB"->"AB""CAA"->"CA""ADA"->"AD"
方法总结
以后遇到这种题,你可以这样识别:
这类题的关键词
如果题目里出现这些意思,通常就是这种做法:
- 每
k个一组 - 分块处理
- 保留第一次出现
- 去重但顺序不能乱
这类题的通用套路
套路可以记成两步:
第一步,按固定长度切块:
for i in range(0, len(s), k):
part = s[i:i+k]
第二步,对每一块做“顺序去重”:
seen = set()
result = ""
for ch in part:
if ch not in seen:
seen.add(ch)
result += ch
这个模板以后会很常用。
补充一句:这题为什么要用 set,但又不能“只用 set”?
因为:
set很适合做“某个元素是否已经出现过”的快速判断- 但
set不适合直接承担“保留原顺序”的任务
所以这题是:
- 用
set负责“判重” - 用字符串
result负责“按顺序收集结果”
这就是两个工具配合使用。
练习
你可以先自己做这道同类型小题:
给定字符串:
string = "ABBCCCDD"
k = 2
请按题目同样规则输出结果。
提示
先把它切成 4 段:
"AB""BC""CC""DD"
然后每一段分别做“按顺序去重”。



