统计各位数字都不同的数字个数

标签: 数学 动态规划 回溯

难度: Medium

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

示例 1:

输入:n = 2
输出:91
解释:答案应为除去 11、22、33、44、55、66、77、88、99 外,在 0 ≤ x < 100 范围内的所有数字。 

示例 2:

输入:n = 0
输出:1

提示:

  • 0 <= n <= 8

Submission

运行时间: 20 ms

内存: 0.0 MB

class Solution:
    def countNumbersWithUniqueDigits(self, n: int) -> int:
        if not n:   return 1
        total, start = 10, 9
        for i in range(1, n):
            start = start*(10-i)
            total += start
        return total

Explain

这个题解使用了数学方法来解决问题。对于一个n位数,第一位有9种选择(不能为0),第二位有9种选择,第三位有8种选择,以此类推。所以不同的n位数的个数为9*9*8*...(9-n+2),再加上小于n位数的不同数字的个数,即为最终结果。

时间复杂度: O(n)

空间复杂度: O(1)

class Solution:
    def countNumbersWithUniqueDigits(self, n: int) -> int:
        if not n:   return 1
        total, start = 10, 9  # total为最终结果,start为当前位数不同数字的个数
        for i in range(1, n):
            start = start*(10-i)  # 计算当前位数不同数字的个数
            total += start  # 将当前位数的不同数字个数加到结果中
        return total

Explore

在计算一个n位数时,第一位数字不能为0(除非数字本身是0),因为如果第一位为0,则它不会被视为一个n位数,而是一个n-1位数。例如,'0123'实际上是一个三位数123。因此,第一位的选择范围是1到9,共9种可能。

这种说法基本上是准确的,但表述可能略有混淆。实际上,第二位数字的选择范围应该是除了已经选过的第一位数字之外的所有数字。如果第一位选择了一个数字,那么第二位可以选择的数字实际上是剩下的9个数字(10个数字中去除已经选择的1个)。因此,第二位有10-1=9种选择。

在这种情况下,n=0意味着我们考虑的是0位数字的数量。在数学和数字的定义中,0位数字可以看作是不存在任何数字,即空数列。在这种情况下,我们通常认为存在一个这样的数字,即'数的空集',对应于数字0。因此,对于n=0,我们认为只有一个数(即0),所以输出为1。