问题背景
小M在工作中遇到一个问题,用户输入的数字字符串通常不带千分位逗号,并且可能存在多余的前导零。为了提高数字的可读性,用户希望将输入的数字字符串转换成带有千分位逗号的格式,并且需要保留小数部分。如果输入的数字字符串前有多余的零,这些零也需要去除。该问题实际上是一个数字字符串格式化问题,要求精确处理整数部分和小数部分,并且考虑边界情况。
题目要求
给定一个数字字符串,要求:
- 去除字符串中无用的前导零。
- 将整数部分按照千分位格式化,即每三位添加一个逗号。
- 保留小数部分(如果有),并且不对其进行格式化。
输入与输出
-
输入:
- 一个数字字符串
s,包含整数部分和可选的小数部分,且可能包含无效的前导零。
- 一个数字字符串
-
输出:
- 格式化后的数字字符串,带有千分位逗号,且没有前导零。
例子分析
示例 1
-
输入:
"1294512.12412" -
输出:
'1,294,512.12412'- 该数字字符串已经没有前导零,整数部分
1294512可以被格式化为1,294,512,小数部分保持不变。
- 该数字字符串已经没有前导零,整数部分
示例 2
-
输入:
"0000123456789.99" -
输出:
'123,456,789.99'- 输入的字符串包含前导零,去除后变为
123456789.99,然后整数部分被格式化为123,456,789,小数部分.99保持不变。
- 输入的字符串包含前导零,去除后变为
示例 3
-
输入:
"987654321" -
输出:
'987,654,321'- 该数字字符串没有前导零,整数部分
987654321被格式化为987,654,321。
- 该数字字符串没有前导零,整数部分
解决方案
为了实现这个数字字符串格式化的任务,我们需要以下几个步骤:
-
去除前导零:
- 字符串中的前导零不需要保留,因此可以使用
strip('0')方法去除所有的前导零。需要注意的是,如果去除后字符串为空,表示原输入是一个非常小的数字,如00000,此时应将其视作0。
- 字符串中的前导零不需要保留,因此可以使用
-
分离整数部分和小数部分:
- 如果数字字符串中包含小数点,我们需要将整数部分和小数部分分开。可以使用
split('.')方法,将小数部分与整数部分分开。 - 如果没有小数点,则小数部分为空字符串。
- 如果数字字符串中包含小数点,我们需要将整数部分和小数部分分开。可以使用
-
格式化整数部分:
- 整数部分需要按照千分位格式化。具体方法是将整数部分反转,从右到左每三位插入一个逗号,然后再将结果反转回来。
-
合并整数部分和小数部分:
- 最后,将格式化后的整数部分和原始的小数部分(如果存在)重新组合成最终的格式化字符串。
实现细节
-
去除前导零: 使用 Python 字符串的
strip('0')方法去除所有前导零。如果去除后字符串为空,需要将其设置为'0'。 -
分离整数和小数部分: 使用 Python 的
split('.')方法,如果存在小数点,则可以获得整数部分和小数部分。对于没有小数点的情况,默认将小数部分设置为空字符串。 -
千分位格式化: 通过反转整数部分,遍历每三位添加逗号,并在最后再反转回来。这是一种简单且有效的格式化方法。具体的步骤如下:
- 遍历整数部分,从右到左每三位插入一个逗号。
- 由于是从右到左添加逗号,因此最后需要将结果反转回来。
-
返回结果: 如果存在小数部分,则返回格式化后的整数部分和小数部分合并后的结果;如果没有小数部分,则只返回格式化后的整数部分。
代码实现
python复制代码def solution(s: str) -> str:
# 去除前导零
s = s.lstrip('0')
# 如果去除前导零后字符串为空,说明数字为零
if s == '':
return '0'
# 分离整数部分和小数部分
if '.' in s:
integer_part, decimal_part = s.split('.')
else:
integer_part, decimal_part = s, ''
# 格式化整数部分
formatted_integer_part = ''
for i, char in enumerate(reversed(integer_part)):
if i > 0 and i % 3 == 0:
formatted_integer_part = ',' + formatted_integer_part
formatted_integer_part = char + formatted_integer_part
# 合并整数和小数部分
if decimal_part:
return f"{formatted_integer_part}.{decimal_part}"
else:
return formatted_integer_part
代码解析
- 去除前导零: 使用
s.lstrip('0')方法去除字符串s中的前导零。这个方法返回去除前导零后的字符串。 - 处理空字符串情况: 如果
s为空字符串(即输入的数字全是零),我们返回'0'。 - 分离整数和小数部分: 如果输入字符串中包含小数点(通过
'.' in s判断),则使用split('.')方法将整数部分和小数部分分离。如果没有小数点,则小数部分为空字符串。 - 整数部分的千分位格式化: 遍历整数部分的字符(从右到左),每三位添加一个逗号。具体做法是将整数部分反转,并根据索引插入逗号,最后再将结果反转回来。
- 合并结果: 如果有小数部分,则将格式化后的整数部分和小数部分拼接在一起;如果没有小数部分,只返回格式化后的整数部分。
边界情况
- 输入为零: 如果输入为全零字符串(如
"0000"),经过去除前导零后应返回'0'。 - 没有小数部分的整数: 如果输入是一个整数,如
"1000000",则返回格式化后的整数部分'1,000,000'。 - 只有小数部分的数字: 如果输入只有小数部分(如
"0.999"),则结果应为"0.999"。 - 极小或极大的数字: 该方法同样适用于极小或极大的数字,如
"0.00000001"或"12345678901234567890",它们会按照预期格式化为0.00000001和12,345,678,901,234,567,890。
复杂度分析
-
时间复杂度:
- 去除前导零:
O(n),其中n是字符串的长度。 - 格式化整数部分:
O(n),其中n是整数部分的长度。 - 总体时间复杂度:
O(n)。
- 去除前导零:
-
空间复杂度:
- 空间复杂度:
O(n),用于存储格式化后的字符串。
- 空间复杂度: