class Solution {
public:
int atMostNGivenDigitSet(vector<string>& digits, int n) {
}
};
902. 最大为 N 的数字组合
给定一个按 非递减顺序 排列的数字数组 digits
。你可以用任意次数 digits[i]
来写的数字。例如,如果 digits = ['1','3','5']
,我们可以写数字,如 '13'
, '551'
, 和 '1351315'
。
返回 可以生成的小于或等于给定整数 n
的正整数的个数 。
示例 1:
输入:digits = ["1","3","5","7"], n = 100 输出:20 解释: 可写出的 20 个数字是: 1, 3, 5, 7, 11, 13, 15, 17, 31, 33, 35, 37, 51, 53, 55, 57, 71, 73, 75, 77.
示例 2:
输入:digits = ["1","4","9"], n = 1000000000 输出:29523 解释: 我们可以写 3 个一位数字,9 个两位数字,27 个三位数字, 81 个四位数字,243 个五位数字,729 个六位数字, 2187 个七位数字,6561 个八位数字和 19683 个九位数字。 总共,可以使用D中的数字写出 29523 个整数。
示例 3:
输入:digits = ["7"], n = 8 输出:1
提示:
1 <= digits.length <= 9
digits[i].length == 1
digits[i]
是从 '1'
到 '9'
的数digits
中的所有值都 不同 digits
按 非递减顺序 排列1 <= n <= 109
原站题解
python3 解法, 执行用时: 32 ms, 内存消耗: 15.1 MB, 提交时间: 2022-10-18 15:11:25
class Solution: def atMostNGivenDigitSet(self, digits: List[str], n: int) -> int: ''' dp[i][0] 表示由 digits 构成且 n 的前 i 位的数字的个数, dp[i][1] 表示由 digits 构成且等于 n 的前 i 位的数字的个数, 可知 dp[i][1] 的取值只能为 0 和 1。 ''' m = len(digits) s = str(n) k = len(s) dp = [[0, 0] for _ in range(k + 1)] dp[0][1] = 1 for i in range(1, k + 1): for d in digits: if d == s[i - 1]: dp[i][1] = dp[i - 1][1] elif d < s[i - 1]: dp[i][0] += dp[i - 1][1] else: break if i > 1: dp[i][0] += m + dp[i - 1][0] * m return sum(dp[k])
python3 解法, 执行用时: 44 ms, 内存消耗: 15.1 MB, 提交时间: 2022-10-18 15:08:04
class Solution: def atMostNGivenDigitSet(self, digits: List[str], n: int) -> int: s = str(n) @cache def f(i: int, is_limit: bool, is_num: bool) -> int: if i == len(s): return int(is_num) # 如果填了数字,则为 1 种合法方案 res = 0 if not is_num: # 前面不填数字,那么可以跳过当前数位,也不填数字 # is_limit 改为 False,因为没有填数字,位数都比 n 要短,自然不会受到 n 的约束 # is_num 仍然为 False,因为没有填任何数字 res = f(i + 1, False, False) up = s[i] if is_limit else '9' # 根据是否受到约束,决定可以填的数字的上限 # 注意:对于一般的题目而言,如果此时 is_num 为 False,则必须从 1 开始枚举,由于本题 digits 没有 0,所以无需处理这种情况 for d in digits: # 枚举要填入的数字 d if d > up: break # d 超过上限,由于 digits 是有序的,后面的 d 都会超过上限,故退出循环 # is_limit:如果当前受到 n 的约束,且填的数字等于上限,那么后面仍然会受到 n 的约束 # is_num 为 True,因为填了数字 res += f(i + 1, is_limit and d == up, True) return res return f(0, True, False)