代码解析-数字字符串格式化 | 豆包MarsCode AI刷题

107 阅读2分钟

代码分析

这段代码的主要目的是将用户输入的不带千分位逗号的数字字符串转换为带千分位逗号的格式,并且保留小数部分,同时处理可能存在的前导零和"e"字符的问题。代码整体逻辑清晰,结构合理,具备以下几个亮点:

使用的算法

  1. 正则表达式处理前导零
    使用正则表达式 ^0+(?!$|\.) 来匹配并移除字符串开头的所有零,除非这些零后面紧跟一个小数点或字符串本身就是零(即处理"000123.45"和"0."的情况,但保留"0")。
  2. 数字格式化
    利用 DecimalFormat 类,通过设定模式 #,###.########## 来格式化数字。这个模式表示整数部分使用千分位逗号分隔,小数部分保留最多10位小数(可以根据需求调整)。

数据结构

  • 字符串 (String) :输入和输出的数据类型都是字符串,用于处理数字字符串。
  • 正则表达式 (Pattern) :虽然代码中未显式声明 Pattern 对象,但 replaceAll 方法内部使用了正则表达式引擎。
  • DecimalFormat:用于数字格式化的类,内部可能使用了一些复杂的数据结构(如字符数组、状态机等)来处理数字格式,但这些细节对代码的使用者来说是透明的。

优点

  1. 健壮性:代码处理了多种特殊情况,如空字符串、仅包含小数点的字符串、前导零等,确保输出的格式总是正确的。
  2. 灵活性:小数位数可以通过修改 DecimalFormat 的模式来调整,满足不同的需求。
  3. 可读性:代码逻辑清晰,注释详细,易于理解和维护。
  4. 异常处理:虽然理论上不应该抛出 ParseException,但代码仍然包含了异常处理,提高了程序的健壮性。
import java.text.ParseException;  
import java.text.NumberFormat;  
import java.util.Locale;  
  
public class Main {  
    public static String solution(String s) {  
        // 移除前导零  
        s = s.replaceAll("^0+(?!$|\\.)", "");  
        // 如果整个字符串被移除成空或仅剩下一个小数点,则特别处理为 "0"  
        if (s.isEmpty() || s.equals(".")) {  
            return "0";  
        }  
  
        // 使用 DecimalFormat 进行格式化  
        DecimalFormat df = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US);  
        df.applyPattern("#,###.##########"); // 保留最多10位小数,可以根据需要调整  
  
        try {  
            Number num = df.parse(s);  
            return df.format(num);  
        } catch (ParseException e) {  
            // 理论上这里不会抛出异常,因为输入已经是数字字符串  
            // 但为了代码的健壮性,还是保留了异常处理  
            e.printStackTrace();  
            return "0"; // 或者其他错误处理方式  
        }  
    }  
  
    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"));  
        System.out.println(solution(".123").equals("0.123"));  
        System.out.println(solution("0.123").equals("0.123"));  
        // 可以添加更多测试用例来验证  
    }  
}

空间复杂度和时间复杂度

  • 空间复杂度
    代码中的空间复杂度主要集中在字符串处理和 DecimalFormat 对象的创建上。由于字符串是不可变的,因此每次操作(如 replaceAll)都会生成新的字符串对象。此外,DecimalFormat 对象内部可能使用了一些额外的空间来存储格式信息。总体而言,空间复杂度与输入字符串的长度成正比。

  • 时间复杂度

    • 正则表达式匹配replaceAll 方法的时间复杂度通常与输入字符串的长度和正则表达式的复杂度有关。在这里,正则表达式的复杂度是固定的,因此时间复杂度与输入字符串的长度成正比。
    • 数字格式化DecimalFormat.parse 和 DecimalFormat.format 方法的时间复杂度也与输入字符串的长度有关,因为它们需要遍历整个字符串来解析和格式化数字。

综上所述,这段代码的时间复杂度和空间复杂度都是线性的,即 O(n),其中 n 是输入字符串的长度。这种复杂度对于处理大多数数字字符串来说是合理的,并且在实际应用中表现良好。

总结

这段代码通过使用正则表达式和 DecimalFormat 类,有效地解决了将不带千分位逗号的数字字符串转换为带千分位逗号格式的问题,同时保留了小数部分,并处理了前导零和特殊字符的问题。代码结构清晰,逻辑严谨,具备良好的可读性和健壮性,是处理此类问题的有效解决方案。