跳到主要内容

HJ31. 单词倒排

题目描述​

对字符串中的所有单词进行倒排,单词之间以空格分隔。"单词"由字母(A-Za-z)构成;字符串中的非字母字符(空格、数字、标点等)视为单词间的分隔符。

输入格式​

  • 一行字符串(可能含空格、数字、标点)。

输出格式​

  • 倒排后的单词序列,单词间以单个空格分隔。

示例​

示例 1​

输入:

I am a student

输出:

student a am I

示例 2​

输入:

$bo*y gi!r#l

输出:

l r gi y bo

说明: $bo*y gi!r#l 中字母单词为 bo、y、gi、r、l,倒排为 l r gi y bo。


解题思路​

第一步:理解问题本质​

把连续字母视为一个单词,非字母字符全部视为分隔符,将单词序列倒序后以单空格连接。

第二步:暴力解法(手动扫描)​

手动遍历字符串,遇到字母收集成单词,遇到非字母结束当前单词,再反转单词列表。

问题:需要自己维护状态,处理连续分隔符、开头结尾分隔符等边界较繁琐。

第三步:优化解法(正则提取)​

用正则 re.findall(r'[A-Za-z]+', s) 一次提取所有连续字母单词,自动跳过所有非字母分隔符。

第四步:最优解法(正则 + 反转拼接)​

提取单词列表后直接反转,用空格连接即可。

words = re.findall(r'[A-Za-z]+', s)  # 提取所有单词
print(' '.join(words[::-1]))

完整代码实现​

本题无可视化步骤:代码里没有可逐帧展示的过程(执行轨迹已经录下来, 但局部变量里找不到推进中的中间状态 —— 比如全篇就是一次正则替换或一次切片)。

import sys
import re


def solve() -> None:
"""主求解函数"""
s = sys.stdin.readline().strip()
words = re.findall(r'[A-Za-z]+', s) # 提取所有单词
print(' '.join(words[::-1]))


if __name__ == "__main__":
solve()

示例推演​

以示例 2 $bo*y gi!r#l 为例:

提取单词: 正则 [A-Za-z]+ 匹配所有连续字母:

  • $ 非字母,跳过
  • bo → 单词
  • * 非字母,跳过
  • y → 单词
  • 非字母,跳过
  • gi → 单词
  • ! 非字母,跳过
  • r → 单词
  • # 非字母,跳过
  • l → 单词

得到单词列表 ['bo', 'y', 'gi', 'r', 'l']。

反转并连接: ['l', 'r', 'gi', 'y', 'bo'] → l r gi y bo。


复杂度分析​

解法时间复杂度空间复杂度说明
手动扫描O(L)O(L)需处理多种分隔符边界
正则提取O(L)O(L)正则自动处理分隔符

L 为字符串长度


易错点总结​

1. 单词仅由字母构成​

单词只包含 A-Za-z,数字、标点、空格都不是单词的一部分,而是分隔符。

2. 连续分隔符​

多个非字母字符连续出现时不能产生空单词,正则 + 自动保证不会匹配到空串。

3. 反转整个列表​

是单词列表整体反转,而不是每个单词内部反转,注意 words[::-1] 的位置。

4. 输出用单空格​

倒排后的单词之间以单个空格分隔,不要保留原分隔符。


扩展思考​

  • 正则 [A-Za-z]+ 匹配连续字母,是处理"按某类字符分割"的通用技巧。
  • 若单词允许其他字符,只需调整正则的字符集即可,例如 [\w]+。

相关题目​

自测​

加载评论中...