Given an integer n, count the total number of digit 1 appearing in all non-negative integers less than or equal to n.
做了半天才发现人家要的是 1 这个 digit 的数量,不是 number 的数量, 又改了改,好歹是通过了, 但是代码确实丑。凑活看吧。
本来开始想用反向思维来解, 就是总数-所有不包含 1 的数字数量, 但是好像不太灵, 后来又发现是要 digit 的数量, 所以就彻底放弃直接用 dp 的方法来解 dp(i, reach_top, ones), i 代表第 i 位数字(从 0 开始), reach_top 代表前一位数字是不是已经达到最大值, ones 代表当前的 1 的数量。如果 reach_top = true, 那我们就只能从 0…=digits[i]中来挑选当前位的数字, 否则, 我们就可以从 0…=9 中选择。对于最后一位的处理同样要考虑 reach_top 和 ones, 具体的看代码吧
use std::collections::HashMap;
impl Solution {
fn rc(digits: &Vec<i32>, i: usize, reach_top: bool, ones: i32, cache: &mut HashMap<(usize, bool, i32), i32>) -> i32 {
let mut ans = 0;
// 如果是最后一位
if i == digits.len() - 1 {
// 如果上一位已经是最大
if reach_top {
// 如果前面的几位中已经包含1
if ones > 0 {
// 如果当前位为0, 将前面几位的1计入答案
if digits[i] == 0 {
ans += ones;
return ans;
}
// 如果当前位大于0, 当当前位不为1的时候每个数字都对答案贡献ones, 当当前位位1时, 该数字对答案贡献ones + 1
ans += digits[i] * ones;
ans += ones + 1;
return ans;
}
// 如果前面几位不包含1且当前为大于0, 只有当前位为1的时候,向答案贡献1
if digits[i] > 0 {
ans += 1;
return ans;
}
// 如果前几位不包含1且当前位为0, 没有任何包含1的数字可用
return 0;
}
// 如果上一位不是最大, 且前几位包含1, 当当前位不为1时, 每个数字向答案贡献ones, 当当前位为1时, 每个数字向答案贡献ones+1
if ones > 0 {
ans += 9 * ones;
ans += ones + 1;
return ans;
}
// 如果上一位不是最大, 且前几位不包含1, 只有当前位为1时向答案贡献1
ans += 1;
return ans;
}
if reach_top {
for j in 0..=digits[i] {
let next = if let Some(c) = cache.get(&(i + 1, j == digits[i], ones + if j == 1 { 1 } else { 0 })) {
*c
} else {
Solution::rc(digits, i + 1, j == digits[i], ones + if j == 1 { 1 } else { 0 }, cache)
};
ans += next;
}
} else {
for j in 0..10 {
let next = if let Some(c) = cache.get(&(i + 1, false, ones + if j == 1 { 1 } else { 0 })) {
*c
} else {
Solution::rc(digits, i + 1, false, ones + if j == 1 { 1 } else { 0 }, cache)
};
ans += next;
}
}
cache.insert((i, reach_top, ones), ans);
ans
}
pub fn count_digit_one(n: i32) -> i32 {
let digits: Vec<i32> = n.to_string().chars().map(|c| c.to_string().parse::<i32>().unwrap()).collect();
if digits.len() == 1 {
if digits[0] == 0 {
return 0;
}
return 1;
}
let mut ans = 0;
let mut cache = HashMap::new();
for d in 0..=digits[0] {
ans += Solution::rc(&digits, 1, d == digits[0], if d == 1 { 1 } else { 0 }, &mut cache);
}
ans as i32
}
}

该博客介绍了LeetCode第233题的解决方案,重点是计算在所有非负整数中数字1出现的总次数。作者使用动态规划的方法,通过dp数组来跟踪不同位置上数字1的数量,考虑了前一位是否达到最大值的情况。代码虽然起初遇到理解问题,但最终成功实现并得到正确结果。
2545

被折叠的 条评论
为什么被折叠?



