一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情。
题目链接:357. 统计各位数字都不同的数字个数
题目描述
给你一个整数 n ,统计并返回各位数字都不同的数字 x 的个数,其中 。
提示:
0 <= n <= 8
示例 1:
输入:n = 2
输出:91
解释:答案应为除去 11、22、33、44、55、66、77、88、99 外,在 0 ≤ x < 100 范围内的所有数字。
示例 2:
输入:n = 0
输出:1
题意整理
这里题目中的 n 没有表述很清楚,我们可以结合题意和样例了解到这里的 n 表示数字最多有 n 位。所以题意就是当数字不超过 n 位时, 各位数字都不相同 的数字有多少个。
解题思路分析
我们根据题目给定的 n 可以确定数字的范围,如 n = 2 时,数字的范围为 ,注意这里不包含 。首先考虑边界特殊情况,这里题目 示例2 给出了边界 n = 0 的情况答案为 1,此时我们还需考虑 n = 1 的情况,因为考虑到数字不能有前导零,但是当数字只有一位的时候有 0 存在,所以考虑特殊情况 n = 1 的时候,只有一位,没有其他位数字的存在, 都是符合要求的答案,即输出 10 ,然后考虑 n = 2 的时候,第一位不能是 0 所以第一位有 9 种数字可以选 (),那么第二位数字为了不与第一位数字相同,只能在剩下的数字中选取,但是注意第二位可以选择数字 0,所以第二位有 9 种数字可以选取,那么由排列组合和乘法原理,我们得知当数字为 2 位时总共有 9 * 9 = 81 个数字的各位数字都不相同,那么加上数字为 1 位时的数字个数总共就有 10 + 81 = 91 种。到这里我们可以得到一般规律,含有 位数的各位数字都不同的数字 x 的个数可以由公式 计算。再加上含有小于 d 位数的各位数字都不同的数字 x 的个数,即可得到答案。
复杂度分析
- 时间复杂度:,仅使用一个循环。
- 空间复杂度:,仅使用常数空间。
具体实现
- 首先特判处理边界和特殊情况:
- 当
n = 0时,,x只有 种选择,即 。 - 当
n = 1时,,x有 种选择,即 。
- 当
- 有两位数的
x可以由组合数学进行计算:第一位的选择有 种,即 ,第二位的选择也有 种,即 中除去第一位的选择。 - 含有 位数的各位数字都不同的数字
x的个数可以由公式 计算。再加上含有小于d位数的各位数字都不同的数字x的个数,即可得到答案。
代码实现
class Solution {
public:
int countNumbersWithUniqueDigits(int n) {
//边界(0)和特殊情况(1)的处理
if (n == 0) return 1;
if (n == 1) return 10;
//答案总数包含n = 1的10种,当前可以选择的数字种数cur为9
int ans = 10, cur = 9;
//剩下的n - 1位数字
for (int i = 0; i < n - 1; ++i) {
//减去前面的位数,剩下的就是可以选择的种数
cur *= 9 - i;
//答案加上当前位数的[各位数字都不同]的数字个数
ans += cur;
}
return ans;
}
};
总结
该题因数据非常小,还可以通过打表的方式将所有 n 对应的答案输出即可(switch(n));包括递归和动态规划都是可以的方法。
该题还有进阶版本——题目链接:1012. 至少有 1 位重复的数字
结束语
人生,其实是很公平的。在哪里付出,就在哪里得到;在哪里打磨,就在哪里闪耀。时光不负有心人,等你埋头走了很长的路,抬头时就可以看见满天星辰。愿你怀揣期许,努力向上。