字符串切片

题目考点

这道题主要考这几个点:

  1. 字符串切片
  2. 循环分组处理
  3. 去重,但要保留原来的先后顺序
  4. 函数题的输出方式

这题表面看起来像“字符串题”,但真正的核心是:

把一个大字符串按长度 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"

开始遍历:

  • Aseen 里没有
    result = "A"
    seen = {"A"}
  • 再看 A,已经在 seen
    跳过
  • Bseen 里没有
    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"

然后每一段分别做“按顺序去重”。

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇