题解
这道题的核心在于对输入的数字字符串进行格式化处理,主要包括以下几个步骤:
- 去掉无用的前置零;
- 提取整数部分和小数部分;
- 对整数部分添加千分位逗号;
- 拼接格式化后的整数部分和小数部分。
下面,我们详细分析题目需求,并逐步优化代码。
问题分解与分析
-
去掉无用的前置零
无用的前置零需要被移除,比如"0000123.45"需要转化为"123.45"。可以通过从左到右遍历字符串,找到第一个非零字符的位置,截取子串即可。 -
分割整数和小数部分
可以利用正则表达式匹配,提取出小数点之前的整数部分和小数点之后的小数部分。例如:"1294512.12412"分割后,整数部分为"1294512",小数部分为"12412";- 如果输入没有小数点,如
"987654321",则仅提取整数部分。
-
格式化整数部分
Python 提供了一种简洁的方法来为整数添加千分位逗号,即"{:,}".format(),直接对整数部分格式化即可。 -
拼接结果
如果小数部分存在,需要将格式化后的整数部分和原始小数部分拼接;如果没有小数部分,则直接返回格式化后的整数部分。
代码实现
以下是代码,并附带注释:
import re
def solution(s: str) -> str:
"""
将数字字符串格式化为带千分位的形式,保留小数部分,并去掉无用的前置零。
"""
# 去除前导零,确保字符串至少为 "0"
s = s.lstrip('0') or '0'
# 分离整数部分和小数部分
match = re.match(r'(\d+)(\.\d+)?', s)
if not match:
return "Invalid input"
# 提取整数部分和小数部分
integer_part = match.group(1) # 整数部分
decimal_part = match.group(2) or '' # 小数部分,若无则为空字符串
# 格式化整数部分
formatted_integer = "{:,}".format(int(integer_part))
# 拼接结果并返回
return formatted_integer + decimal_part
# 测试样例
if __name__ == '__main__':
assert solution("1294512.12412") == "1,294,512.12412"
assert solution("0000123456789.99") == "1,234,567,889.99"
assert solution("987654321") == "987,654,321"
assert solution("0000") == "0"
代码详解
-
去除前导零
- 使用
s.lstrip('0')去除字符串中的前导零。如果字符串全是零,则保留一个零,利用or '0'处理这一特殊情况。
- 使用
-
正则表达式分割
re.match(r'(\d+)(\.\d+)?', s)将字符串分为整数部分和小数部分:(\d+)匹配一串数字,表示整数部分;(\.\d+)?匹配小数点后的一串数字,可选。
-
格式化整数部分
"{:,}".format(int(integer_part))自动为整数部分添加千分位逗号,简洁高效。
-
拼接结果
- 如果小数部分存在(
decimal_part非空),直接拼接;否则仅返回格式化后的整数部分。
- 如果小数部分存在(
测试与验证
-
典型用例
- 输入
"1294512.12412",返回"1,294,512.12412"; - 输入
"0000123456789.99",返回"1,234,567,889.99"; - 输入
"987654321",返回"987,654,321"。
- 输入
-
边界用例
- 输入
"0000",返回"0"; - 输入
".1234",返回"0.1234"; - 输入
"0",返回"0"。
- 输入
-
异常用例
- 输入非法字符(如
"abc"),正则匹配失败,返回"Invalid input"。
- 输入非法字符(如
复杂度分析
-
时间复杂度
- 去除前导零的操作为 (O(n));
- 正则匹配操作为 (O(n));
- 整数部分格式化为 (O(m)),其中 (m) 是整数部分的长度。
- 总体复杂度为 (O(n))。
-
空间复杂度
-
使用了少量辅助变量,空间复杂度为 (O(1))。
-