问题描述
小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’的字符。
- 分割整数和小数部分:接下来,我们需要将数字字符串分割成整数部分和小数部分。这可以通过查找字符串中的小数点(‘.’)来实现。如果存在小数点,则将字符串分割成两部分;如果不存在,则整个字符串都是整数部分。
- 格式化整数部分:然后,我们需要对整数部分进行格式化,以添加千分位逗号。这可以通过创建一个
DecimalFormat
对象并使用它的format
方法来实现。 - 拼接结果:最后,我们将格式化后的整数部分与原始的小数部分(如果存在)拼接起来,形成最终的字符串。
以下是具体的步骤:
-
步骤1:去除前导零
- 如果字符串以’0’开头,并且长度大于1,则循环去除前导零,直到字符串以非’0’字符开头或者只剩下一个字符。
-
步骤2:分割整数和小数部分
- 使用
String.split
方法,以’.'为分隔符,将字符串分割成两部分。
- 使用
-
步骤3:格式化整数部分
- 创建
DecimalFormat
对象,并设置格式为"#,###"。 - 使用
DecimalFormat.format
方法格式化整数部分。
- 创建
-
步骤4:拼接结果
- 如果存在小数部分,则将格式化后的整数部分和原始的小数部分拼接起来。
- 如果不存在小数部分,则直接返回格式化后的整数部分。
代码实现
import java.math.BigDecimal;
import java.text.DecimalFormat;
public class Main {
public static String solution(String s) {
// write code here
BigDecimal number = new BigDecimal(s);
String[] parts = number.toPlainString().split("\\.");
DecimalFormat df = new DecimalFormat("#,###");
String integerPart = df.format(new BigDecimal(parts[0]));
if (parts.length > 1) {
return integerPart + "." + parts[1];
}else {
return integerPart;
}
}
public static void main(String[] args) {
System.out.println(solution("1294512.12412").equals("1,294,512.12412"));
System.out.println(solution("0000123456789.99").equals("123,456,789.99"));
System.out.println(solution("987654321").equals("987,654,321"));
}
}
复杂度分析
时间复杂度
-
BigDecimal对象创建:
BigDecimal number = new BigDecimal(s);
- 创建
BigDecimal
对象的时间复杂度主要取决于字符串s
的长度,记为n
。该操作的时间复杂度大致为O(n)
,因为需要遍历整个字符串来构建数字。
-
字符串分割:
String[] parts = number.toPlainString().split("\.");
- 分割操作的时间复杂度也是
O(n)
,因为需要遍历整个字符串来找到小数点(如果存在)。
-
DecimalFormat对象创建和格式化:
DecimalFormat df = new DecimalFormat("#,###");
- 创建
DecimalFormat
对象的时间复杂度是常数时间,即O(1)
。 String integerPart = df.format(new BigDecimal(parts[0]));
- 格式化操作的时间复杂度与整数部分的长度有关,记为
m
(m <= n
)。格式化操作的时间复杂度大致为O(m)
,因为需要遍历整数部分来插入逗号。
-
字符串拼接:
return integerPart + "." + parts[1];
- 字符串拼接的时间复杂度取决于拼接的字符串长度,记为
k
(k <= n
)。字符串拼接的时间复杂度大致为O(k)
。
综上所述,整个solution
方法的时间复杂度主要取决于字符串s
的长度,可以近似为O(n)
。
空间复杂度
-
BigDecimal对象:
- 创建
BigDecimal
对象的空间复杂度是O(n)
,因为它需要存储数字的每一位。
- 创建
-
字符串数组:
String[] parts
的空间复杂度是O(1)
,因为不管输入字符串多长,数组最多只有两个元素。
-
DecimalFormat对象:
- 创建
DecimalFormat
对象的空间复杂度是O(1)
。
- 创建
-
临时字符串:
integerPart
和返回的最终字符串的空间复杂度是O(n)
,因为它们最多与输入字符串等长。
综上所述,整个solution
方法的空间复杂度也是O(n)
,因为需要存储与输入字符串等长的临时字符串。