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的好数计数问题/