在这道题目中,我们需要将一个数字字符串格式化为具有千位分隔符的形式。具体来说,我们需要对整数部分添加逗号(,)分隔符,使得每三位数字后面有一个逗号,以便让数字更易读。
输入输出格式:
- 输入: 一个字符串
s,表示一个数字(可能包含小数点),可能包含前导零。 - 输出: 返回一个格式化后的字符串,将整数部分以千位分隔符表示,小数部分保持不变。
例如:
- 输入
"1294512.12412"输出"1,294,512.12412" - 输入
"0000123456789.99"输出"123,456,789.99" - 输入
"987654321"输出"987,654,321"
解题思路:
为了实现这一目标,我们可以将问题分解为以下几个步骤:
-
拆分整数和小数部分:
- 通过找到小数点位置,将输入字符串分为整数部分和小数部分。如果没有小数点,就只有整数部分。
-
格式化整数部分:
- 对整数部分进行格式化,每隔三位插入一个逗号。可以通过从后往前处理字符串来实现这一点。
-
合并整数和小数部分:
- 格式化后的整数部分与小数部分合并形成最终结果。
-
处理前导零:
- 在格式化整数部分时,需要去掉前导零。
#include <string>
#include <iostream>
#include <algorithm>
std::string solution(const std::string& s) {
// 1. 找到小数点的位置
size_t dot_pos = s.find('.');
// 2. 如果没有小数点,dot_pos = std::string::npos
std::string integer_part = s;
std::string decimal_part = "";
// 如果有小数部分
if (dot_pos != std::string::npos) {
integer_part = s.substr(0, dot_pos);
decimal_part = s.substr(dot_pos); // 包括小数点及其后面的部分
}
// 3. 去掉整数部分的前导零
integer_part = std::to_string(std::stoll(integer_part)); // 转为整数再转回字符串,去除前导零
// 4. 对整数部分进行千位分隔符处理
std::string formatted_integer = "";
int length = integer_part.length();
// 从右往左,每三位添加一个逗号
for (int i = length - 1; i >= 0; --i) {
formatted_integer = integer_part[i] + formatted_integer;
if ((length - i) % 3 == 0 && i != 0) {
formatted_integer = "," + formatted_integer;
}
代码讲解:
-
拆分整数和小数部分:
- 我们首先使用
find方法找到字符串中小数点的位置。如果有小数点,则使用substr方法将整数部分和小数部分分开。没有小数点时,小数部分为空字符串。
- 我们首先使用
-
去除前导零:
- 对于整数部分,我们使用
stoll将其转换为整数,自动去掉前导零,然后再将其转换回字符串。
- 对于整数部分,我们使用
-
格式化整数部分:
- 我们从整数部分的末尾开始,逐个字符向前处理,每当经过三位数字时,就插入一个逗号。
-
合并结果:
- 最后,将格式化后的整数部分与小数部分拼接起来返回。
示例分析:
示例 1:
输入:"1294512.12412"
- 整数部分为
"1294512",小数部分为".12412"。 - 格式化整数部分得到
"1,294,512"。 - 合并后结果为
"1,294,512.12412"。
示例 2:
输入:"0000123456789.99"
- 整数部分为
"123456789"(去掉了前导零),小数部分为".99"。 - 格式化整数部分得到
"123,456,789"。 - 合并后结果为
"123,456,789.99"。
示例 3:
输入:"987654321"
- 整数部分为
"987654321",没有小数部分。 - 格式化整数部分得到
"987,654,321"。
时间复杂度:
- 由于我们处理每个字符最多一次,时间复杂度是 O(n),其中 n 是输入字符串的长度。
空间复杂度:
- 由于我们使用了额外的字符串来存储格式化后的结果,空间复杂度是 O(n)。
总结:
这道题目通过模拟字符串的格式化过程解决问题。主要的难点在于处理整数部分的千位分隔符,以及正确处理小数部分和前导零。