leetcode刷题记录-357. 统计各位数字都不同的数字个数

132 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第10天,点击查看活动详情

前言

今天的题目为中等,难点在于能否意识到可以把多位数的情况转为前面的结果相加,想到的话就能够很好地利用递归进行解题。

每日一题

今天的题目是 357. 统计各位数字都不同的数字个数,难度为中等

  • 给你一个整数 n ,统计并返回各位数字都不同的数字 x 的个数,其中 0 <= x < 10n 。  

示例 1:

输入:n = 2
输出:91
解释:答案应为除去 112233445566778899 外,在 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];
};

image.png

递归+数学

题目要统计每一位都不同的数字的个数,首先要优先考虑两种比较特使的情况,就是当 n 为 0 或者 n 为 1 的时候,分别有着 1 和 10 个解。

然后剩下的数字涉及到关于数学排列组合的相关知识,比如说当 n 为 2 的时候,这时候一位数的情况就是 n 为 1 的结果,关于两位数的部分,就可以看做 第一位 和 第二位 的一个组合,这时候的第一位有着 9 种可能的值,分别为 1-9 第二位也有着 9 种可能的值,分别是 0-9 去掉 第一位

image.png

如果是三位数的情况类似,第三位有着8种情况,不能和前两位相等,以此类推,我们就能够的到,n 的范围最大不能够超过 10 当然题目要求也就到 8 而已,并且通过 第一位 9 种可能 第二位 9 种 可能,第三位 8 种。。。最后能够得到一个方程式

image.png

并且在代码中要实现这个方程式,我们可以用递归实现,每次都计算出当前位数的答案个数即可,向函数中返回 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)
};

image.png