328不大于n的好数计数问题
问题描述
小 C 定义一个正整数为“好数”,当且仅当这个数的相邻数位都不相同。比如,1024 和 121 是好数,但 233 不是。现在小 C 想知道,不大于给定整数 n 的好数有多少个。结果对 $10^9 + 7$ 取模。
解题思路
转换为字符串:首先将整数
n
转换为字符串s
,以便逐位处理。定义状态:
i
:当前处理到第i
位。pre
:前一位的数字,用于判断当前位是否与前一位不同。is_limit
:当前位是否受到上界的限制,即前面的数字是否已经与n
的对应位相同。is_num
:当前是否已经开始构造数字(避免前导零)。
递归函数
dfs
:- 当
i
等于len(s)
时,表示所有位都已经处理完毕,如果已经开始构造数字,则返回1
,否则返回0
。 - 如果尚未开始构造数字,可以选择跳过当前位(即不选择任何数字)。
- 对于每一位,可以选择从
0
到9
(根据is_limit
确定上界)。 - 选择的数字
d
需要与前一位数字pre
不同。 - 递归处理下一位,更新状态参数。
- 当
记忆化搜索:使用
@cache
装饰器对递归函数进行记忆化,以避免重复计算,提高效率。结果:最终返回符合条件的“好数”数量,对
10^9 + 7
取模。
代码解析
1 |
|
复杂度分析
- 时间复杂度:
O(len(s) * 10 * 10)
,其中len(s)
是整数n
的位数,每一位有10
种选择。动态规划的时间复杂度 = 状态个数 × 单个状态的计算时间 - 空间复杂度:
O(len(s) * 10)
,用于记忆化存储中间结果。
328不大于n的好数计数问题
https://kongshuilinhua.github.io/2025/01/21/328不大于n的好数计数问题/