跳到主要内容

HJ96. 表示数字

题目描述​

将字符串中每一个连续的数字串用符号 * 括起来,其余字符不变。

输入格式​

一行字符串(可能含字母、数字等)。

输出格式​

处理后的字符串:每个连续数字段前后各加一个 *。

示例​

示例 1​

输入:

Jkdi234klowe90a3

输出:

Jkdi*234*klowe*90*a*3*

说明: 数字段 234、90、3 分别被 * 括起来。


解题思路​

第一步:理解问题本质​

要识别所有连续的数字串(\d+),在每个数字串前后插入一个 *,非数字字符原样保留。

第二步:暴力解法(逐字符扫描)​

遍历每个字符,判断是否数字,跟踪连续数字段的开始和结束,在段首段尾手动插入 *。

问题:需要维护多个状态(是否在数字段、段起始位置),代码繁琐且易错。

第三步:优化解法(正则替换)​

连续数字串用正则 \d+ 一次匹配,替换为 *\1*(\1 引用捕获到的数字串):

result = re.sub(r'(\d+)', r'*\1*', s)

正则引擎自动识别所有连续数字段,代码简洁可靠。

第四步:关于手写扫描​

如果不想依赖正则,也可用一次线性扫描:遇到数字时找到连续数字段的结束位置,输出 * + 数字段 + *,然后跳过该段。两种方法都是最优的 O(n),正则实现更简洁。


完整代码实现​

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

import sys
import re


def solve() -> None:
s = sys.stdin.readline().strip()
# 连续数字段用 * 括起来
result = re.sub(r'(\d+)', r'*\1*', s)
print(result)


if __name__ == "__main__":
solve()

示例推演​

以示例 1 为例,输入 Jkdi234klowe90a3。

正则 \d+ 依次匹配到三个数字段:

  • 234 → 替换为 *234*
  • 90 → 替换为 *90*
  • 3 → 替换为 *3*

其余字符 Jkdi、klowe、a 保持不变。

最终结果:Jkdi*234*klowe*90*a*3*。


复杂度分析​

解法时间复杂度空间复杂度说明
逐字符扫描O(n)O(n)需维护状态机
正则替换O(n)O(n)简洁可靠

n 为字符串长度


易错点总结​

1. 连续数字段被拆开​

若用 \d 而非 \d+ 逐个替换,每个数字单独加 *,会破坏连续数字段。必须用 \d+ 一次匹配整段。

2. 替换语法写错​

捕获组要用括号 (\d+),替换串用 *\1* 引用;漏掉括号或 \1 会导致错误。

3. 空字符串​

输入为空时,re.sub 返回空串,直接输出空行即可。


扩展思考​

  • 正则替换是处理字符串模式匹配的利器,可扩展处理连续字母、连续标点等类似需求。
  • 若要求在每个数字段内部的每个数字也加 *,则属于另一个问题,需用 \d 逐个替换。

相关题目​

自测​

加载评论中...