Medium
题目描述
给你一个整数 n ,统计并返回各位数字都不同的数字 x 的个数,其中 0 ≤ x < 10^n 。
示例 1:
输入:n = 2
输出:91
解释:答案应为除去 11、22、33、44、55、66、77、88、99 外,在 0 ≤ x < 100 范围内的所有数字。
示例 2:
输入:n = 0
输出:1
提示:
- 0 ≤ n ≤ 8
解题提示:
- 直接方法是使用回溯法
- 回溯应该包含三个状态:当前数字、构成该数字的步数、以及表示当前数字中已访问数字的位掩码
- 也可以使用动态规划和组合数学知识解决
- 设 f(k) = 长度为 k 且各位数字都不同的数字个数
- f(1) = 10,f(k) = 9 × 9 × 8 × … × (9 - k + 2)(第一个因子是9因为数字不能以0开头)
解题思路
这道题可以用数学组合的方法来解决,这是最优解法。
核心思路:
- 对于 n 位数字,我们需要统计所有位数小于等于 n 且各位数字都不同的数字个数
- 分别计算 1位数、2位数、…、n位数的各位数字都不同的数字个数
计算方法:
- 1位数:0-9,共10个数字,都满足条件
- k位数 (k≥2):
- 第一位不能是0,有9种选择 (1-9)
- 第二位不能与第一位相同,有9种选择 (包括0,但排除第一位)
- 第三位不能与前两位相同,有8种选择
- …
- 第k位有 (11-k) 种选择
- 所以k位数的个数为:9 × 9 × 8 × … × (11-k)
特殊情况:
- n=0 时,只有数字0符合条件,返回1
- 当 n>10 时,由于数字只有0-9共10个,无法构成超过10位的各位数字都不同的数字
其他解法:
- 回溯法:枚举所有可能的数字组合,用位掩码记录已使用的数字
- 动态规划:状态为当前位数和已使用数字的集合
数学解法时间复杂度最优,推荐使用。
代码实现
class Solution {
public:
int countNumbersWithUniqueDigits(int n) {
if (n == 0) return 1;
int result = 10; // 1位数:0-9
int uniqueDigits = 9;
int availableNumber = 9;
while (n-- > 1 && availableNumber > 0) {
uniqueDigits = uniqueDigits * availableNumber;
result += uniqueDigits;
availableNumber--;
}
return result;
}
};
class Solution:
def countNumbersWithUniqueDigits(self, n: int) -> int:
if n == 0:
return 1
result = 10 # 1位数:0-9
unique_digits = 9
available_number = 9
while n > 1 and available_number > 0:
unique_digits *= available_number
result += unique_digits
available_number -= 1
n -= 1
return result
public class Solution {
public int CountNumbersWithUniqueDigits(int n) {
if (n == 0) return 1;
int result = 10; // 1位数:0-9
int uniqueDigits = 9;
int availableNumber = 9;
while (n-- > 1 && availableNumber > 0) {
uniqueDigits *= availableNumber;
result += uniqueDigits;
availableNumber--;
}
return result;
}
}
var countNumbersWithUniqueDigits = function(n) {
if (n === 0) return 1;
let result = 10; // for n = 1: 0-9
let uniqueDigits = 9; // first digit choices (1-9)
let availableDigits = 9; // remaining digit choices
for (let i = 2; i <= n; i++) {
uniqueDigits *= availableDigits;
result += uniqueDigits;
availableDigits--;
}
return result;
};
复杂度分析
| 复杂度类型 | 大小 |
|---|---|
| 时间复杂度 | O(n) |
| 空间复杂度 | O(1) |