一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第9天,点击查看活动详情。
题目描述
给你一个整数 n ,统计并返回各位数字都不同的数字 x 的个数,其中 0 <= x < 。
示例 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 < ,其实就是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=0和n=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);
}
}