java简单算法题002 数字字符串格式化(保姆级教学)

问题描述

小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'

 答案

public class Main {
    public static String solution(String s) {
        // PLEASE DO NOT MODIFY THE FUNCTION SIGNATURE
        // write code here
        // 去除前面的零
        s = s.replaceFirst("^0+(?!$)", "");

        // 分离整数部分和小数部分
        String[] parts = s.split("\\.");
        String integerPart = parts[0];
        String decimaPart = parts.length > 1 ? parts[1] : "";

        // 在适当位置插入逗号
        // 计数器count
        int count = 0;
        // 用StringBilider对字符串进行动态构建
        StringBuilder sb = new StringBuilder();
        // 从右往左遍历整数部分
        for (int i = integerPart.length() - 1; i >= 0; i--) {
            // 从右往左把整数部分添加到sb中
            sb.append(integerPart.charAt(i));
            count++;
            // 当达到三个后添加逗号
            if (count % 3 == 0 && i != 0) {
                sb.append(",");
            }
        }
        // 将字符串反转
        sb.reverse();

        // 进行字符串的拼接
        return sb.toString() + (decimaPart.isEmpty() ? "" : "." + decimaPart);
    }

    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"));
    }
}

 解析

1.问题理解

我们需要将一个不带千分位逗号的数字字符串转换为带千分位逗号的格式,并且保留小数部分。此外,输入的数字字符串前面可能会有无用的 0,这些也需要精简掉。

2.算法步骤

  1. 去除前导零:首先,我们需要去除输入字符串前面的无用 0。可以使用 String.replaceFirst("^0+(?!$)", "") 来实现这一点。

  2. 分离整数部分和小数部分:接下来,我们需要将字符串分为整数部分和小数部分。可以使用 String.split("\\.") 来实现这一点。

  3. 处理整数部分:对于整数部分,我们需要从右往左每三位插入一个逗号。可以使用 StringBuilder 来构建结果字符串,并在适当的位置插入逗号。

  4. 合并结果:最后,将处理后的整数部分和小数部分(如果有)合并成最终的结果字符串。

3.代码分段解析

去除前面的零
// 去除前面的零
s = s.replaceFirst("^0+(?!$)", "");
  1. String.replaceFirst 方法:

    • replaceFirst 方法用于替换字符串中第一个匹配正则表达式的子字符串
    • 在这里,replaceFirst("^0+(?!$)", "") 会将字符串开头的一个或多个 0 替换为空字符串,从而去除这些前导零。
  2. **正则表达式 ^0+(?!$)**:

    • ^:表示字符串的开始。
    • 0+:表示一个或多个 0
    • (?!$):这是一个负向前瞻断言,表示匹配的 0 后面不能是字符串的结尾。

    这个正则表达式的意思是:匹配字符串开头的一个或多个 0,但这些 0 不能是字符串的结尾。

  3. 正则表达式中的前瞻断言

    在正则表达式中,前瞻断言(lookahead assertion)用于检查某个位置之后是否存在某种模式,而不实际匹配该模式。前瞻断言有两种类型:

    正向前瞻断言(?=...),表示匹配位置之后必须存在某种模式。
    负向前瞻断言(?!...),表示匹配位置之后不能存在某种模式。

    (?!$) 的解释:
    (?!...):这是一个负向前瞻断言。
     $:表示字符串的结尾。
    因此,(?!$) 表示匹配的位置之后不能是字符串的结尾。

     

    示例

    假设我们有以下输入字符串:
    "0000123456789.99"
    ^0+ 会匹配字符串开头的所有 0,即 "0000"
    (?!$) 会检查这些 0 后面是否不是字符串的结尾。

     在 "0000123456789.99" 中,0000 后面是 1,不是字符串的结尾,因此匹配成功。

    这样就有效避免了输入0但是把它变为空字符串的结果
  4. 正则表达式中的 ^ 符号

    在正则表达式中,^ 符号有两种主要用途:

    在字符集(character class)中
    例如 [^0-9],表示匹配任何不是数字的字符。 
    在字符集之外
    例如 ^0+,表示匹配字符串的开始位置。

分离整数和小数部分
        // 分离整数部分和小数部分
        String[] parts = s.split("\\.");
        String integerPart = parts[0];
        String decimaPart = parts.length > 1 ? parts[1] : "";

 

  1. 字符串分割
    在Java中,String.split 方法用于将字符串根据指定的分隔符分割成多个子字符串,并返回一个字符串数组。

  2. String.split("\\.") 的解释
    split 方法的参数是一个正则表达式。
    \\.:表示匹配一个点(.)。在正则表达式中,. 是一个特殊字符,表示匹配任意字符。因此,我们需要使用 \\ 进行转义,使其匹配实际的点字符。

  3. 示例

    假设我们有以下输入字符串:
    "123456789.99"
    String[] parts = "123456789.99".split("\\.");
    parts[0] 将是 "123456789"(整数部分)。
    parts[1] 将是 "99"(小数部分)。
    使用 split("\\.") 进行分割:

用StringBilder对字符串进行动态构建
        // 用StringBilider对字符串进行动态构建
        StringBuilder sb = new StringBuilder();
        // 从右往左遍历整数部分
        for (int i = integerPart.length() - 1; i >= 0; i--) {
            // 从右往左把整数部分添加到sb中
            sb.append(integerPart.charAt(i));
            count++;
            // 当达到三个后添加逗号
            if (count % 3 == 0 && i != 0) {
                sb.append(",");
            }
        }
        // 将字符串反转
        sb.reverse();
  1. 为什么使用StringBilder ?
    StringBuilder 是一个可变的字符串类,非常适合用于字符串的动态构建和修改。我们可以使用 StringBuilder 来逐步构建结果字符串,并在适当的位置插入逗号。
  2. 具体步骤

    **初始化 StringBuilder**:创建一个新的 StringBuilder 对象。
    从右往左遍历整数部分:使用一个循环从整数部分的末尾开始,逐个字符添加到 StringBuilder 中。
    插入逗号:每添加三个字符后,插入一个逗号。
    反转字符串:由于我们是倒序添加字符的,最后需要将 StringBuilder 中的字符串反转。

 

        // 合并整数部分和小数部分
        return sb.toString() + (decimalPart.isEmpty() ? "" : "." + decimalPart);
  1.  sb.toString():将 StringBuilder 对象 sb 转换为字符串。
  2. decimalPart.isEmpty():检查 decimalPart 是否为空字符串。
    decimalPart 是从输入字符串中分离出来的小数部分。
  3. (decimalPart.isEmpty() ? "" : "." + decimalPart):这是一个三元运算符,用于根据 decimalPart 是否为空来决定是否拼接小数部分。

    如果 decimalPart 为空,返回空字符串 ""
    如果 decimalPart 不为空,返回 "." + decimalPart,即在整数部分后面加上小数点和小数部分。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值