问题描述
小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'
算法设计
- 去除字符串中前导的无用零。
- 特殊情况处理,如果去除前导零后字符串为空或只包含小数点,返回 "0"。
- 分离字符串的整数部分和小数部分。
- 给分离出来的整数部分添加千分位逗号。
- 组合整数部分和小数部分,将整数部分和小数部分连接起来,返回最终格式化的字符串。
算法复杂度分析
1、去除前导的无用零(Java):
时间复杂度:O(n),其中 n 是字符串的长度。正则表达式的匹配和替换操作通常线性于字符串的长度。
空间复杂度:O(n),因为 replaceFirst 会创建一个新的字符串。
2、处理特殊情况(Java):
时间复杂度:O(1),常数时间操作。
空间复杂度:O(1),常数空间。
3、分离整数部分和小数部分(Java):
时间复杂度:O(n),contains 和 indexOf 都是线性时间操作,substring 也是线性时间操作。
空间复杂度:O(n),因为 substring 会创建新的字符串。
4、在整数部分添加千分位逗号(Java):
时间复杂度:O(n),遍历整数部分的每个字符。
空间复杂度:O(n),StringBuilder 会创建一个新的字符串。
5、组合整数部分和小数部分(Java):
时间复杂度:O(n),字符串拼接操作。
空间复杂度:O(n),创建新的字符串。
总体时间复杂度和空间复杂度(Java)
时间复杂度:O(n),所有操作都是线性时间。
空间复杂度:O(n),所有操作都涉及创建新的字符串。
代码
Java 代码实现
public class Main {
public static String solution(String s) {
// 去除前导的无用零
s = s.replaceFirst("^0+(?!$)", "");
// 如果字符串为空或只包含小数点,返回 "0"
if (s.isEmpty() || s.equals(".")) {
return "0";
}
// 分离整数部分和小数部分
String integerPart;
String decimalPart = "";
if (s.contains(".")) {
int dotIndex = s.indexOf('.');
integerPart = s.substring(0, dotIndex);
decimalPart = s.substring(dotIndex);
} else {
integerPart = s;
}
// 在整数部分添加千分位逗号
integerPart = addCommasToIntegerPart(integerPart);
// 组合整数部分和小数部分
return integerPart + decimalPart;
}
private static String addCommasToIntegerPart(String integerPart) {
StringBuilder formatted = new StringBuilder();
int length = integerPart.length();
for (int i = 0; i < length; i++) {
if (i > 0 && (length - i) % 3 == 0) {
formatted.append(',');
}
formatted.append(integerPart.charAt(i));
}
return formatted.toString();
}
// 测试
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"));
}
}
Go 代码实现
package main
import (
"fmt"
"strings"
)
func solution(s string) string {
// 去除前导的无用零
s = strings.TrimLeft(s, "0")
// 如果字符串为空或只包含小数点,返回 "0"
if s == "" || s == "." {
return "0"
}
// 分离整数部分和小数部分
integerPart := s
decimalPart := ""
if strings.Contains(s, ".") {
parts := strings.Split(s, ".")
integerPart = parts[0]
decimalPart = "." + parts[1]
}
// 在整数部分添加千分位逗号
integerPart = addCommasToIntegerPart(integerPart)
// 组合整数部分和小数部分
return integerPart + decimalPart
}
func addCommasToIntegerPart(integerPart string) string {
// 使用 StringBuilder 来构建带千分位逗号的整数部分
var sb strings.Builder
length := len(integerPart)
for i := 0; i < length; i++ {
if i > 0 && (length-i)%3 == 0 {
sb.WriteRune(',')
}
sb.WriteByte(integerPart[i])
}
return sb.String()
}
// 测试
func main() {
fmt.Println(solution("1294512.12412") == "1,294,512.12412")
fmt.Println(solution("0000123456789.99") == "123,456,789.99")
fmt.Println(solution("987654321") == "987,654,321")
}
Python 代码实现
def solution(s: str) -> str:
# 去除前导的无用零
s = s.lstrip('0')
# 如果字符串为空或只包含小数点,返回 "0"
if not s or s == '.':
return '0'
# 分离整数部分和小数部分
if '.' in s:
integer_part, decimal_part = s.split('.')
else:
integer_part, decimal_part = s, ''
# 在整数部分添加千分位逗号
integer_part = '{:,}'.format(int(integer_part))
# 组合整数部分和小数部分
if decimal_part:
return f"{integer_part}.{decimal_part}"
else:
return integer_part
# 测试
if __name__ == '__main__':
print(solution("1294512.12412") == '1,294,512.12412')
print(solution("0000123456789.99") == '123,456,789.99')
print(solution("987654321") == '987,654,321')