一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第10天,点击查看活动详情。
前言
今天的题目为中等,难点在于能否意识到可以把多位数的情况转为前面的结果相加,想到的话就能够很好地利用递归进行解题。
每日一题
今天的题目是 357. 统计各位数字都不同的数字个数,难度为中等
- 给你一个整数 n ,统计并返回各位数字都不同的数字 x 的个数,其中 0 <= x < 10n 。
示例 1:
输入:n = 2
输出:91
解释:答案应为除去 11、22、33、44、55、66、77、88、99 外,在 0 ≤ x < 100 范围内的所有数字。
示例 2:
输入:n = 0
输出:1
提示:
- 0 <= n <= 8
题解
面向测试编程
由于题目给出的 n 范围很小,所以直接模拟出所有的结果,暴力解答。
/**
* @param {number} n
* @return {number}
*/
var countNumbersWithUniqueDigits = function (n) {
return [1, 10, 91, 739, 5275, 32491, 168571, 712891, 2345851][n];
};
递归+数学
题目要统计每一位都不同的数字的个数,首先要优先考虑两种比较特使的情况,就是当 n 为 0 或者 n 为 1 的时候,分别有着 1 和 10 个解。
然后剩下的数字涉及到关于数学排列组合的相关知识,比如说当 n 为 2 的时候,这时候一位数的情况就是 n 为 1 的结果,关于两位数的部分,就可以看做 第一位 和 第二位 的一个组合,这时候的第一位有着 9 种可能的值,分别为 1-9 第二位也有着 9 种可能的值,分别是 0-9 去掉 第一位
如果是三位数的情况类似,第三位有着8种情况,不能和前两位相等,以此类推,我们就能够的到,n 的范围最大不能够超过 10 当然题目要求也就到 8 而已,并且通过 第一位 9 种可能 第二位 9 种 可能,第三位 8 种。。。最后能够得到一个方程式
并且在代码中要实现这个方程式,我们可以用递归实现,每次都计算出当前位数的答案个数即可,向函数中返回 n-1 去计算少一位的结果。
/**
* @param {number} n
* @return {number}
*/
var countNumbersWithUniqueDigits = function(n) {
if(n == 0)
return 1
let res = 9
for(let i = 9; i > 10 - n; i--){
res *= i
}
return res + countNumbersWithUniqueDigits(n - 1)
};