leetcode-统计各位数字都不同的数字个数

172 阅读1分钟

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

题目描述

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

示例 1:
输入:n = 2
输出:91
解释:答案应为除去 11、22、33、44、55、66、77、88、99 外,在 0 ≤ x < 100 范围内的所有数字。

示例 2:
输入:n = 0
输出:1

提示:
0 <= n <= 8

思路

根据题意,满足 0 <= x < 10n10^n ,其实就是X从0开始取自然数,直到最大的n位数。例如n=3,就是x要满足0 <= x < 999。显然,我们可以对不同长度的自然数分开计算,然后再累加起来。这样,这里整体是可以递归的,我们要求解f(n),如果f(n-1)是已知的,我们可以写出递推公式

f(n) = f(n-1) + n位自然数满足各位数字都不同的数字的数字数量

那么问题就简化成了,如何求解“n位自然数满足各位数字都不同的数字的数字数量”。这里我们可以通过排列的数量来求解。

  • 对于最高位,不能为0,包含9种可能(1~9)
  • 左起第2位,本来有10种可能(0~9),排除最高位的数,这里还有9种可能
  • 左起第3位,本来有10种可能(0~9),排除最高位的数和左起第2位,这里还有8种可能
  • 左起第4位,本来有10种可能(0~9),排除前3位使用的数,这里还有7种可能 以此类推。。。

这里有注意点是n=0n=1这2个边界的情况,我们先讨论掉:

  • n=0 0 <= x < 1,此时x只能等于0,所以这里只有1个数满足条件
  • n=1 0 <= x < 10,此时最高位也是最低位,所以是可以等于0的,跟上面说的最高位不能为0不同,这里有10个数满足条件
    去掉边界情况后,我们再按照上面的思路做递归即可。

Java版本代码

class Solution {
    public int countNumbersWithUniqueDigits(int n) {
        if (n == 0) {
            return 1;
        }
        if (n == 1) {
            return 10;
        }
        int ans = 9*9;
        for (int i = 2; i < n; i++) {
            ans *= (10 - i);
        }
        return ans + countNumbersWithUniqueDigits(n-1);
    }
}