LC 2719. 统计整数数目
还没有接触过这种数位 dp 的算法,我看了一下 讲解,大致思路就是:
- 将上限数字转变成为字符串
- 从第 0 个数字开始匹配
- 如果处于受限状态,那么就最多只能到对应数字上,否则就可以到 9
- 主要是针对字符串上的每个位置进行枚举
下面是题主给出的模板
- i 表示枚举的位置,从开头进行枚举
- sum 表示当前所有累计的数字之和
- isNum 表示当前是否得到的是有效数字,因为起始我么允许使用"000" 这样的,所有 isNum 开始就是 true. 这个里面可以省略
- isLimit 表示前缀是否被锁定
class Solution: def count(self, num1: str, num2: str, min_sum: int, max_sum: int) -> int: def doCount(num): s = str(num) from functools import cache @cache def f(i, sum, isNum, isLimit): if sum > max_sum: return 0 if i == len(s): return sum >= min_sum and isNum res = 0 down = 0 if isNum else 1 up = int(s[i]) if isLimit else 9 for d in range(down, up + 1): res += f(i + 1, sum + d, True, isLimit and d == up) return res return f(0, 0, True, True) a = doCount(num2) b = doCount(num1) c = (min_sum <= sum(map(int, num1)) <= max_sum) ans = (a - b) + c return ans
题主还给了这个题作为学习 https://leetcode.cn/problems/numbers-with-repeated-digits/
这题里面就需要维护一个 mask. 然后这题里面起始不允许出现前缀 0 这样的答案,所以一开始 isNum = false
class Solution: def numDupDigitsAtMostN(self, n: int) -> int: s = str(n) from functools import cache @cache def f(i, mask, isNum, isLimit): if i == len(s): return isNum res = 0 if not isNum: res += f(i + 1, mask, False, False) down = 0 if isNum else 1 up = int(s[i]) if isLimit else 9 for d in range(down, up + 1): if not (mask & (1 << d)): res += f(i + 1, mask | (1 << d), True, isLimit and d == up) return res a = f(0, 0, False, True) ans = n - a return ans