豆包大模型 MarsCode AI 刷题专栏 002
003.数字字符串格式化
难度:易
问题描述
小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'
进行:
-
去除前导零:首先,我们需要去除输入字符串中的前导零。可以使用Python的
lstrip
方法来去除字符串前面的零。 -
分离整数和小数部分:接下来,我们需要将字符串分成整数部分和小数部分。如果字符串中包含小数点,我们可以使用
split
方法将其分割成两部分。 -
处理整数部分:对于整数部分,我们需要从右向左每三位插入一个逗号。可以使用Python的切片和字符串拼接来实现这一点。
-
重新组合整数和小数部分:最后,将处理后的整数部分和小数部分重新组合成一个字符串。
具体步骤
-
去除前导零:
使用lstrip('0')
去除字符串前面的零。 -
分离整数和小数部分:
使用split('.')
将字符串分割成整数部分和小数部分。 -
处理整数部分:
从右向左遍历整数部分,每三位插入一个逗号。可以使用切片和字符串拼接来实现。 -
重新组合整数和小数部分:
如果存在小数部分,将处理后的整数部分和小数部分用小数点连接起来;否则,直接返回处理后的整数部分。
通过这些步骤,我们可以将输入的数字字符串转换为带千分位逗号的格式,并且保留小数部分。
复杂度分析
-
时间复杂度:
- 字符串分割和格式化操作的时间复杂度为 O(n),其中 n 是字符串的长度。
- 去除多余字符的操作时间复杂度为 O(n)。
- 总体时间复杂度为 O(n)。
-
空间复杂度:
- 主要的空间开销在于存储分割后的整数部分和小数部分,以及格式化后的字符串。
- 总体空间复杂度为 O(n)。
知识点扩展
-
字符串处理:
- 字符串的分割、拼接和格式化是字符串处理中的基本操作。
- 使用
split
方法可以根据指定的分隔符将字符串分割成多个部分。 - 使用
format
方法可以对字符串进行格式化输出,例如添加千分位逗号。
-
字符串的去除操作:
rstrip
方法用于去除字符串末尾指定的字符。- 在本题中,
rstrip('0').rstrip('.')
用于去除小数部分末尾多余的0
和小数点。
MarsCode AI答案
Python:
def solution(s: str) -> str:
# 去除前导零
s = s.lstrip('0')
# 分离整数和小数部分
if '.' in s:
integer_part, fractional_part = s.split('.')
else:
integer_part, fractional_part = s, ''
# 添加千分位逗号
if integer_part:
integer_part = ''.join(reversed(integer_part)) # 反转字符串
integer_part = ','.join(integer_part[i:i+3] for i in range(0, len(integer_part), 3)) # 每三位加一个逗号
integer_part = ''.join(reversed(integer_part)) # 再次反转回来
# 合并整数和小数部分
result = integer_part
if fractional_part:
result += '.' + fractional_part
return result
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')
from collections import Counter
def solution(s:str) -> str:
if '.' in s:
integer_part, decimal_part = s.split('.')
else:
integer_part, decimal_part = s, None
formatted_integer = "{:,}".format(int(integer_part))
if decimal_part:
s = formatted_integer + '.' + decimal_part
else:
s = formatted_integer
return s.rstrip('0').rstrip('.')
if __name__ == '__main__':
print(solution(s = "1294512.12412") == '1,294,512.12412')
print(solution(s = "0000123456789.99") == '123,456,789.99')
print(solution(s = "987654321") == '987,654,321')
Go:
package main
import (
"fmt"
"strings"
)
func solution(s string) string {
// 去除前导零
s = strings.TrimLeft(s, "0")
if s == "" {
s = "0"
}
// 分离整数和小数部分
parts := strings.Split(s, ".")
integerPart := parts[0]
var decimalPart string
if len(parts) > 1 {
decimalPart = "." + parts[1]
}
// 处理整数部分,从右向左每三位插入一个逗号
var result strings.Builder
for i, char := range integerPart {
if i > 0 && (len(integerPart)-i)%3 == 0 {
result.WriteRune(',')
}
result.WriteRune(char)
}
// 合并结果
result.WriteString(decimalPart)
return result.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")
}
Rust:
fn solution(s: &str) -> String {
// 去除前导零
let s = s.trim_start_matches('0');
// 分离整数部分和小数部分
let parts: Vec<&str> = s.split('.').collect();
let integer_part = parts[0];
let decimal_part = if parts.len() > 1 { parts[1] } else { "" };
// 处理整数部分,添加千分位逗号
let mut result = String::new();
let len = integer_part.len();
for (i, ch) in integer_part.chars().enumerate() {
if i > 0 && (len - i) % 3 == 0 {
result.push(',');
}
result.push(ch);
}
// 如果存在小数部分,添加小数点和小数部分
if !decimal_part.is_empty() {
result.push('.');
result.push_str(decimal_part);
}
result
}
fn main() {
println!("{}", solution("1294512.12412") == "1,294,512.12412");
println!("{}", solution("0000123456789.99") == "123,456,789.99");
println!("{}", solution("987654321") == "987,654,321");
}
004.数字分组求偶数和
难度:易
问题描述
小M面对一组从 1 到 9 的数字,这些数字被分成多个小组,并从每个小组中选择一个数字组成一个新的数。目标是使得这个新数的各位数字之和为偶数。任务是计算出有多少种不同的分组和选择方法可以达到这一目标。
numbers
: 一个由多个整数字符串组成的列表,每个字符串可以视为一个数字组。小M需要从每个数字组中选择一个数字。
例如对于[123, 456, 789]
,14个符合条件的数为:147 149 158 167 169 248 257 259 268 347 349 358 367 369
。
测试样例
样例1:
输入:
numbers = [123, 456, 789]
输出:14
样例2:
输入:
numbers = [123456789]
输出:4
样例3:
输入:
numbers = [14329, 7568]
输出:10
问题理解
我们需要从每个数字组中选择一个数字,使得这些数字的和为偶数。关键在于理解如何判断一个数的和是否为偶数。
关键点
-
偶数和奇数的性质:
- 偶数 + 偶数 = 偶数
- 奇数 + 奇数 = 偶数
- 偶数 + 奇数 = 奇数
-
选择策略:
- 如果一个数字组中既有奇数又有偶数,那么我们可以灵活选择,使得最终的和为偶数。
- 如果一个数字组中只有奇数或只有偶数,那么我们需要根据其他数字组的选择来决定当前组的选择。
数据结构选择
- 我们可以使用集合来存储每个数字组中的奇数和偶数。
- 然后通过组合这些奇数和偶数来计算符合条件的组合数。
算法步骤
1.初始化:
- 遍历每个数字组,将每个数字组中的奇数和偶数分别存储在两个集合中。
2.组合计算:
- 如果所有数字组中都有奇数和偶数,那么我们可以任意组合。
- 如果某些数字组中只有奇数或只有偶数,我们需要根据其他数字组的选择来决定当前组的选择。
3.计算符合条件的组合数:
- 通过组合奇数和偶数的数量来计算符合条件的组合数。
解题过程
-
初始化状态:
- 初始时,
f[0]
表示当前选择的数字之和为偶数的方案数,初始值为1(即空集的情况)。 f[1]
表示当前选择的数字之和为奇数的方案数,初始值为0。
- 初始时,
-
遍历每个数字组:
对于每个数字组,统计其中奇数和偶数的个数,分别记为c[0]
和c[1]
。
-
更新状态:
- 更新
f[0]
为f[0] * c[0] + f[1] * c[1]
,即当前选择的数字之和为偶数的方案数。 - 更新
f[1]
为f[0] * c[1] + f[1] * c[0]
,即当前选择的数字之和为奇数的方案数。
- 更新
-
返回结果:
最终,f[0]
即为所求的符合条件的方案数。
复杂度分析
-
时间复杂度:
- 遍历每个数字组的时间复杂度为 O(n),其中 n 是数字组的长度。
- 对于每个数字组,统计奇数和偶数的个数的时间复杂度为 O(m),其中 m 是数字组中数字的位数。
- 因此,总的时间复杂度为 O(n×m)。
-
空间复杂度:
- 仅使用了常数级别的额外空间,空间复杂度为 O(1)。
知识点扩展
-
动态规划:
- 动态规划是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。在这道题目中,我们通过定义两个状态
f[0]
和f[1]
来表示当前选择的数字之和为偶数和奇数的方案数,并通过状态转移方程来更新这两个状态。
- 动态规划是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。在这道题目中,我们通过定义两个状态
-
位运算:
- 位运算是一种高效的计算方法,特别是在处理二进制问题时。在这道题目中,我们使用
int(ch) & 1
来判断一个数字是奇数还是偶数,这是一种常见的位运算技巧。
- 位运算是一种高效的计算方法,特别是在处理二进制问题时。在这道题目中,我们使用
MarsCode AI答案
Python:
def solution(numbers: list) -> int:
f = [1, 0]
for x in numbers:
c = [0, 0]
for ch in str(x):
c[int(ch) & 1] += 1
f = [f[0] * c[0] + f[1] * c[1], f[0] * c[1] + f[1] * c[0]]
return f[0]
if __name__ == '__main__':
print(solution(numbers = [123, 456, 789]) == 14)
print(solution(numbers = [123456789]) == 4)
print(solution(numbers = [14329, 7568]) == 10)
Go:
def solution(numbers: list) -> int:
f = [1, 0]
for x in numbers:
c = [0, 0]
for ch in str(x):
c[int(ch) & 1] += 1
f = [f[0] * c[0] + f[1] * c[1], f[0] * c[1] + f[1] * c[0]]
return f[0]
if __name__ == '__main__':
print(solution(numbers = [123, 456, 789]) == 14)
print(solution(numbers = [123456789]) == 4)
print(solution(numbers = [14329, 7568]) == 10)
Rust:
fn solution(numbers: &[String]) -> i32 {
// 用于存储所有可能的组合
let mut combinations = Vec::new();
// 递归函数,用于生成所有可能的组合
fn generate_combinations(numbers: &[String], index: usize, current: &mut String, combinations: &mut Vec<String>) {
if index == numbers.len() {
combinations.push(current.clone());
return;
}
for ch in numbers[index].chars() {
current.push(ch);
generate_combinations(numbers, index + 1, current, combinations);
current.pop();
}
}
// 生成所有可能的组合
generate_combinations(numbers, 0, &mut String::new(), &mut combinations);
// 计算符合条件的组合数量
let mut count = 0;
for combination in combinations {
let sum: i32 = combination.chars().map(|ch| ch.to_digit(10).unwrap() as i32).sum();
if sum % 2 == 0 {
count += 1;
}
}
count
}
fn main() {
// 测试样例
println!("{}", solution(&["123".to_string(), "456".to_string(), "789".to_string()]) == 14);
println!("{}", solution(&["123456789".to_string()]) == 4);
println!("{}", solution(&["14329".to_string(), "7568".to_string()]) == 10);
}
来源:https://www.marscode.cn/practice