【C/C++】357. 统计各位数字都不同的数字个数

207 阅读1分钟

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


题目链接:357. 统计各位数字都不同的数字个数

题目描述

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

提示:

  • 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 时,数字的范围为 0x<1000 \leqslant x < 100 ,注意这里不包含 100100。首先考虑边界特殊情况,这里题目 示例2 给出了边界 n = 0 的情况答案为 1,此时我们还需考虑 n = 1 的情况,因为考虑到数字不能有前导零,但是当数字只有一位的时候有 0 存在,所以考虑特殊情况 n = 1 的时候,只有一位,没有其他位数字的存在,090 \sim 9 都是符合要求的答案,即输出 10 ,然后考虑 n = 2 的时候,第一位不能是 0 所以第一位有 9 种数字可以选 (191 \sim 9),那么第二位数字为了不与第一位数字相同,只能在剩下的数字中选取,但是注意第二位可以选择数字 0,所以第二位有 9 种数字可以选取,那么由排列组合和乘法原理,我们得知当数字为 2 位时总共有 9 * 9 = 81 个数字的各位数字都不相同,那么加上数字为 1 位时的数字个数总共就有 10 + 81 = 91 种。到这里我们可以得到一般规律,含有 d2d10d (2 \le d \le 10)位数的各位数字都不同的数字 x 的个数可以由公式 9×A9d19 \times A_9^{d-1} 计算。再加上含有小于 d 位数的各位数字都不同的数字 x 的个数,即可得到答案。

复杂度分析

  • 时间复杂度:O(n)O(n),仅使用一个循环。
  • 空间复杂度:O(1)O(1),仅使用常数空间。

具体实现

  1. 首先特判处理边界和特殊情况:
    • 当 n = 0 时,0x<10 \leqslant x \lt 1x 只有 11 种选择,即 00
    • n = 1 时,0x<100 \leqslant x \lt 10x1010 种选择,即 090 \sim 9
  2. 有两位数的 x 可以由组合数学进行计算:第一位的选择有 99 种,即 191 \sim 9,第二位的选择也有 99 种,即 090 \sim 9 中除去第一位的选择。
  3. 含有 d2d10d (2 \le d \le 10)位数的各位数字都不同的数字 x 的个数可以由公式 9×A9d19 \times A_9^{d-1} 计算。再加上含有小于 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 位重复的数字


结束语

人生,其实是很公平的。在哪里付出,就在哪里得到;在哪里打磨,就在哪里闪耀。时光不负有心人,等你埋头走了很长的路,抬头时就可以看见满天星辰。愿你怀揣期许,努力向上。