LC 902. 最大为 N 的数字组合 (opens new window) (opens new window)
困难
# 问题描述
给定一个按 非递减顺序 排列的数字数组 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
# 数学
可以分成位数小于指定数字和位数等于指定数字两种情况:
- 当位数小于给出数字的位数时,可以生成的数字数量为可选数字的全排列。
- 当位数等于给出数字的位数时,可以分成两种情况:
- 当前位数对应的数字小于指定数字的对应位数的数字时,后续可以生成的数量为后面位数的全排列。
- 当前位数对应的数字等于指定数字的对应位数的数字时,后一个数可选小于指定数字的对应位数的数字。
对于情况二,可以使用深度优先搜索进行查找,最终结果为两种情况之和。
/**
* @param {string[]} digits
* @param {number} n
* @return {number}
*/
var atMostNGivenDigitSet = function (digits, n) {
const sn = n.toString()
const N = digits.length
const K = sn.length
let ans = 0
for (let i = 1; i < K; i++) {
ans += Math.pow(N, i)
}
const dfs = (len, isLess) => {
if (len === K) return 1
if (isLess) {
return Math.pow(N, K - len)
}
let cnt = 0
for (const digit of digits) {
if (digit > sn[len]) break
if (digit < sn[len]) {
cnt += dfs(len + 1, true)
} else {
cnt += dfs(len + 1, false)
}
}
return cnt
}
return ans + dfs(0, false)
}
- 时间复杂度:,其中 为给定数字, 表示给定的数字的种类。
- 空间复杂度:。
上次更新: 2023/01/31 19:48:05
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 , 转载请注明出处!