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]
)
Hint:
- A direct way is to use the backtracking approach.
- Backtracking should contains three states which are (the current number, number of steps to get that number and a bitmask which represent which number is marked as visited so far in the current number). Start with state (0,0,0) and count all valid number till we reach number of steps equals to 10n.
- This problem can also be solved using a dynamic programming approach and some knowledge of combinatorics.
- Let f(k) = count of numbers with unique digits with length equals k.
- f(1) = 10, ..., f(k) = 9 * 9 * 8 * ... (9 - k + 2) [The first factor is 9 because a number cannot start with 0].
给定非负整数n,要求在0到10^n的范围内(左闭右开),统计所有各位不相同的数字的个数。
思路
简单地数学分析一下:
设在p中取q进行排列的排列数为P(p,q),本题所求结果为A(n),容易得到以下结果:
- n = 0, 0 ≤ x < 1 with unique digits is 0, A(0) = 1
- n = 1, 0 ≤ x < 10 can be divided into
0本身:0 ≤ x < 1 (0本身) : A(0) = 1
1位数:1 ≤ x < 10 (10个数取一个) :
所以A(1) = P(10,1) - 1
- n = 2, 0 ≤ x < 100 with unique digits can be divided into
0本身:0 ≤ x < 1 (0本身): A(0) = 1
1位数:1 ≤ x < 10 (10个数取一个): A(1) = P(10,1) - 1
2位数:10 ≤ x < 100 (10个数取两个,不放回进行排列,但要去掉0开头的数):
所以A(2) = P(10,2) - P(9,1)
- n>10,根据抽屉原理,一定存在至少两位有一样的数字,不满足题意,A(n)=0
- n≤10,相当于10个数取n个不放回进行全排列,去掉0开头的,则A(n)=P(10,n)-P(9,n-1)=9*P(9,n-1)
- 最后可得结果为分段函数
A(n) = 1 (n = 0)
A(n) = 9 * P(9,n-1) (0 < n ≤ 10)
A(n) = 0 (n > 10)
class Solution {
public:
int permutation(int n, int r)
{
if(r == 0)
{
return 1;
}else{
return n * permutation(n - 1, r - 1);
}
}
int countNumbersWithUniqueDigits(int n) {
int sum = 1;
if(n > 0)
{
int end = (n > 10)? 10 : n;
for(int i = 0; i < end; i++)
{
sum += 9 * permutation(9, i);
}
}
return sum;
}
};