357. Count Numbers with Unique Digits

Given a non-negative integer n, count all numbers with unique digits, x, where 0 ≤ x < 10n.

Example:
Given n = 2, return 91. (The answer should be the total numbers in the range of 0 ≤ x < 100, excluding [11,22,33,44,55,66,77,88,99])

递推分析:

n = 0,0<= x < 1, count = 1

n=1, 0 <= x < 10,  count可以看作为 0<= x < 1的个数count(0<= x < 1)加上1<= x < 10的个数count(1<= x < 10)

n = 2, 0 <= x < 100, count可以看作count(0<= x < 1)+count(1<= x < 10)+count(10<= x < 100)

count(0<= x < 1),count(1<= x < 10),count(10<= x < 100)分别记做A[0], A[1], A[2]

A[n], 表示n位数的唯一数字的个数

那么所有求的总个数为sum(n) = A[0] + A[1] + ... + A[n]

A[n]的求法:

A[n]就是从{0, 1, 2,3,4,5,6,7,8,9} 中选取n的排列

A[0] = 1, n = 0

A[n] = C(10, n)*n! - C(9, n-1)*(n-1)! = 10*C(9, n-1)(n-1)! - C(9, n-1)*(n-1)! = 9*C(9, n-1)*(n-1)!, 1 <= n <= 10

A[n] = 0, n > 10

动态规划分析:

dp(i) 表示n=i时,唯一数字个数

当已知i=0,1,n-1,求dp(n)

当n增加1时,增加了数据范围,[10**(n-1),10**n) 数据的位数是n

dp(n) = 1, n = 0 

dp(n) = dp(10), n > 10

dp(n) = dp(n-1) + 9*C(9, n-1)*(n-1)!, 1<= n <= 10

代码:

int permutation(int n, int r)
{
    if (r == 0) {
        return 1;
    }
    
    return n * permutation(n-1, r-1);
}


int countNumbersWithUniqueDigits(int n) {
    //A[0] = 1, n = 0
    //A[n] = C(10, n)*n! - C(9, n-1)*(n-1)! = 9*C(9, n-1)(n-1)!, 1 <= n < 10
    //A[n] = 0, n > 10
    
    int sum = 1; //A[0]
    int i;
    
    if (n > 10) n = 10; //A[n], n>10

    //A[n],[ 1, 10]

    for (i = 1; i <= n; i++) {
        sum += 9 * permutation(9, i-1);
    }
    
    return sum;
}

你可能感兴趣的:(动态规划)