题目来源:LeetCode 357: 统计各位数字都不同的数字个数
问题抽象: 给定一个非负整数 n(0 ≤ n ≤ 8),要求统计区间 [0, 10^n) 内所有 各位数字互不相同 的整数数量,满足以下核心需求:
-
数字表示规则:
- 数字按 十进制表示,忽略前导零(如
5视为一位数5,而非05); - 数字长度可变:范围包含
1位至n位整数(n=0时仅含0)。
- 数字按 十进制表示,忽略前导零(如
-
互异性判定:
- 对任意整数,其 非前导零的实际各位数字 必须 全部不同(如
123合法,122非法); - 单数字(
0 ≤ x ≤ 9)自动满足条件(无重复位)。
- 对任意整数,其 非前导零的实际各位数字 必须 全部不同(如
-
统计约束:
- 需高效计算 累计数量(非暴力枚举),时间复杂度 O(n);
- 数学组合方法:
- 长度为
k的数字数量为9 × P(9, k-1)(首位1-9选一,后k-1位从剩余9数字中排列); - 总数为所有
k ∈ [1, n]的长度累加(k=0时单独处理0)。
- 长度为
-
边界处理:
n=0时,区间[0,1)仅含0→ 输出1;n=1时,区间[0,10)含0-9→ 输出10;n=2时:- 一位数:
0-9(10个); - 两位数:首位
1-9(9种),末位0-9排除首位(9种)→81个; - 总数
10 + 81 = 91;
- 一位数:
n=8时,总数需精确计算(避免整数溢出)。
输入:非负整数 n(0 ≤ n ≤ 8)。
输出:区间 [0, 10^n) 内各位数字互不相同的整数总数(整数值)。
解题思路
题目要求统计在区间 [0, 10^n) 内各位数字都不同的数字个数。可使用排列组合的思想高效求解:
- 边界处理:当
n = 0时,只有数字0,返回 1。 - 一位数处理:一位数(0-9)都满足条件,共 10 个。
- 多位数处理:
- 首位:不能为 0,有 9 种选择(1-9)。
- 后续位:从剩余 9 个数字(0-9 除去首位数字)开始递减选择。
- 公式:k 位数(k ≥ 2)的各位不同的数字个数为
9 × 9 × 8 × ... × (11 - k)。
- 位数限制:当
n > 10时,超过 10 位的数字必然有重复,只需计算到 10 位。 - 累加结果:从 1 位到 n 位,累加所有满足条件的数字个数。
代码实现(Java版)🔥点击下载源码
class Solution {
public int countNumbersWithUniqueDigits(int n) {
// 处理 n = 0 的情况
if (n == 0) {
return 1;
}
// 初始化结果:一位数(0-9)共10个
int res = 10;
// 超过10位无意义,限制 n 最大为10
if (n > 10) {
n = 10;
}
// base:当前位数的数字个数,初始为9(两位数首位9种选择)
int base = 9;
// available:剩余可用数字个数,初始为9(首位后剩余9个数字)
int available = 9;
// 从两位数开始计算到 n 位数
for (int digits = 2; digits <= n; digits++) {
base *= available; // 更新当前位数的数字个数
res += base; // 累加到结果
available--; // 可用数字减少1
}
return res;
}
}
代码说明
- 边界处理:当
n = 0时直接返回 1(只有数字 0)。 - 初始化:
res = 10包含所有一位数(0-9)。 - 限制 n:若
n > 10,则设n = 10(超过 10 位无有效解)。 - 循环计算:
base表示当前位数的有效数字个数,初始为 9(两位数首位 9 种选择)。available表示剩余可用数字,初始为 9(首位后剩余 9 个数字)。- 从两位数开始循环:
- 更新
base = base × available(计算当前位数的数字个数)。 - 累加
base到结果res。 available减 1(已用一个数字)。
- 更新
- 返回结果:累加所有位数的有效数字个数。
提交详情(执行用时、内存消耗)

346

被折叠的 条评论
为什么被折叠?



