数字字符串格式化
问题描述
小M在工作时遇到了一个问题,他需要将用户输入的不带千分位逗号的数字字符串转换为带千分位逗号的格式,并且保留小数部分。小M还发现,有时候输入的数字字符串前面会有无用的 0,这些也需要精简掉。请你帮助小M编写程序,完成这个任务。
测试样例
样例1:
输入:
s = "1294512.12412"
输出:'1,294,512.12412'
样例2:
输入:
s = "0000123456789.99"
输出:'123,456,789.99'
样例3:
输入:
s = "987654321"
输出:'987,654,321'
题解
为了帮助小M解决数字字符串格式化的问题,我们可以从两方面入手:清除无效字符和数字格式化。这里的目标是将一个数字字符串转换为带千分位逗号的格式,同时保留其小数部分,且需要删除数字前多余的无效 0。
问题拆解
-
去除前导
0:
输入的数字字符串可能以多余的0开头,这些需要被清理掉。特别注意,仅为0的字符串不能直接去掉所有0,例如输入"000",输出应该是"0"。-
使用正则表达式
^0+(?!$)可以高效地完成这一任务:^表示匹配字符串开头。0+表示匹配一个或多个连续的0。(?!$)是负向零宽断言,确保后面至少还有其他数字。
-
-
分离整数和小数部分:
通过寻找小数点位置,将字符串分割为整数部分和小数部分。- 如果没有小数点,整个字符串视为整数部分。
- 如果有小数点,将其分割为整数部分和小数部分(包含小数点的部分)。
-
为整数部分添加千分位逗号:
使用一个循环,遍历整数部分,从右向左每三位插入一个逗号。- 为避免频繁插入字符导致性能问题,使用
StringBuilder来处理字符串拼接。
- 为避免频繁插入字符导致性能问题,使用
-
拼接格式化后的结果:
将添加逗号的整数部分和小数部分重新拼接起来,形成最终结果。
以下是完整的 Java 实现:
import java.text.DecimalFormat;
public class Solution {
public static String formatNumber(String s) {
// 去除前导0
s = s.replaceFirst("^0+(?!$)", "");
// 判断是否包含小数点
int decimalIndex = s.indexOf(".");
String integerPart;
String decimalPart = "";
// 分割整数部分和小数部分
if (decimalIndex >= 0) {
integerPart = s.substring(0, decimalIndex);
decimalPart = s.substring(decimalIndex);
} else {
integerPart = s;
}
// 将整数部分添加千分位逗号
StringBuilder sb = new StringBuilder(integerPart);
for (int i = sb.length() - 3; i > 0; i -= 3) {
sb.insert(i, ",");
}
// 拼接整数和小数部分
return sb.toString() + decimalPart;
}
public static void main(String[] args) {
System.out.println("输出: " + formatNumber("1294512.12412")); // 输出应为 "1,294,512.12412"
System.out.println("输出: " + formatNumber("0000123456789.99")); // 输出应为 "123,456,789.99"
System.out.println("输出: " + formatNumber("987654321")); // 输出应为 "987,654,321"
}
}
解释
s.replaceFirst("^0+(?!$)", ""):去掉前导的无用0。正则表达式^0+(?!$)匹配开头的0,但不匹配仅为0的情况。decimalIndex:找到小数点的位置。如果有小数点,则拆分出整数部分和小数部分。StringBuilder和循环:使用StringBuilder将整数部分从右向左每三位插入一个逗号。- 最后将格式化后的整数部分和小数部分拼接,得到结果。
复杂度分析
- 时间复杂度:O(n),其中 n 是字符串的长度。
- 空间复杂度:O(n),用于存储格式化后的结果字符串。