一,题目详情
1,问题描述
小R有一个字符串 word,该字符串由数字和小写英文字母组成。小R想用空格替换每一个不是数字的字符。然后,他希望统计在替换后剩下的整数中,不同整数的数目。
例如,给定字符串 "a123bc34d8ef34",替换后形成的字符串是 " 123 34 8 34",剩下的整数是 "123"、"34"、"8" 和 "34"。不同的整数有三个,即 "123"、"34" 和 "8"。
注意,只有当两个整数的不含前导零的十进制表示不同,才认为它们是不同的整数。
2,测试样例
样例1:
输入:word = "a123bc34d8ef34"
输出:3
样例2:
输入:word = "t1234c23456"
输出:2
样例3:
输入:word = "a1b01c001d4"
输出:2
二,解题思路
1,问题分析
我们需要完成以下任务:
- 将字符串中的所有非数字字符替换为空格。
- 分割字符串,提取所有整数。
- 去除整数的前导零,并统计不同整数的数目。
2,算法策略
核心思想是:
- 使用正则表达式将所有非数字字符替换为空格。
- 使用
split()方法将字符串分割成多个部分。 - 对每个部分去除前导零,并将其加入集合中,利用集合的唯一性来统计不同整数的数目。
具体步骤如下:
- 使用
re.sub(r'[^\d]', ' ', word)将所有非数字字符替换为空格。 - 使用
split()方法将字符串分割成多个部分。 - 对每个部分去除前导零(使用
lstrip('0')),并处理特殊情况(如全为0的情况)。 - 将处理后的整数加入集合中。
- 返回集合的大小,即不同整数的数目。
3,逐步推演(以样例1为例)
输入:word = "a123bc34d8ef34"
-
替换非数字字符为空格:
" 123 34 8 34" -
分割字符串:
["123", "34", "8", "34"] -
去除前导零并加入集合:
{"123", "34", "8"} -
集合大小为3,即不同整数的数目为3。
三,代码实现
import re
def solution(word: str) -> int:
# 将所有非数字字符替换为空格
modified = re.sub(r'[^\d]', ' ', word)
# 分割字符串
parts = modified.split()
# 用于存储不同整数的集合
unique = set()
for part in parts:
# 去除前导零
stripped = part.lstrip('0')
# 处理特殊情况:如果去除前导零后为空,则表示原数字为0
if not stripped:
stripped = '0'
# 将处理后的整数加入集合
unique.add(stripped)
# 返回集合的大小,即不同整数的数目
return len(unique)
1,复杂度分析
-
时间复杂度:O(n)
- 正则替换操作的时间复杂度为 O(n),其中 n 是字符串的长度。
- 分割字符串和处理每个部分的时间复杂度也为 O(n)。
-
空间复杂度:O(n)
- 存储分割后的部分和集合的空间复杂度为 O(n)。
2,边界测试
if __name__ == '__main__':
# 常规测试
print(solution("a123bc34d8ef34") == 3) # 输出: True
print(solution("t1234c23456") == 2) # 输出: True
print(solution("a1b01c001d4") == 2) # 输出: True
# 边界测试:没有数字
print(solution("abcdef") == 0) # 输出: True
# 边界测试:全是数字
print(solution("1234567890") == 1) # 输出: True
# 边界测试:包含前导零
print(solution("a0001b002c03") == 3) # 输出: True
四,总结
通过正则替换、分割字符串和去除前导零,我们实现了:
- 高效替换和统计:利用正则表达式和集合的唯一性
- 清晰的逻辑:分步处理每个部分
- 普适性:适用于所有由数字和小写字母组成的字符串
这种解法不仅高效,还易于理解和实现。当遇到“需要替换字符并统计不同元素”类问题时,正则表达式和集合往往是解决问题的关键工具。