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].
Credits:
Special thanks to @memoryless for adding this problem and creating all test cases.
Subscribe to see which companies asked this question
分析与翻译:
给定一个非负整数 n,计算所有各位数字均不同的数字x的个数,其中0 ≤ x < 10^n。
例子:
给定n=2,答案为91.因为在0-100的数字中除了11,22,33,44,55,66,77,88,99其他所有数各位均不同。
提示:
1)一个直接的办法是使用回溯法。
2)回溯应当包含三个状态(当前数字,得到该数字需要的步数,以及一个比特掩码用来表示当前已经访问过哪些位)。从状态(0,0,0)开始,并计算直到10^n为止的有效数字个数。
3)这个问题也可以使用动态规划方法与一些组合的知识来求解。
4)定义子问题f(k) :长度为k时各位均不同数字的个数。
5)f(1) = 10, ..., f(k) = 9 * 9 * 8 * ... (9 - k + 2) [首个因数是9,因为数字不能从0开始].
分析开始:找规律
既然说可以用动态规划,并且子问题都给你定义好了,那么这个问题就简单了!
n=1时,一位数A,[0,10)显然10个,
n=2时,两位数AB,[0,100),第一位A有9种选择(不能为0),第二位B有9中选择,81种,再加一位的10种,共91种
n=3时,三位数ABC,[0,1000),同理,A有9种可能,B有9种,C有8种...9*9*8+81+10=739
...
所以f(k) = 9 * 9 * 8 * ... (9 - k + 2),我们所做工作只是累加f(1)到f(n)即可,分析完毕。
代码一目了然,不言而喻
class Solution {
public:
int countNumbersWithUniqueDigits(int n) {
int result=0;
for(int i=1;i<=n;i++)
result+=getfk(i);
return result==0?1:result;
}
int getfk(int k)
{
if(k==1)
return 10;
int val=9;
for(int i=2;i<=k;i++)
val*=(9-i+2);
return val;
}
};
简写代码:
class Solution {
public:
int countNumbersWithUniqueDigits(int n) {
if ( n < 0 )
return 0;
int result = 1;
int multiplier = 9;
n = min(n, 10);
for (int i = 1; i <= n; i++) {
result += multiplier;
multiplier *= (i > 9 ? 0: (10 - i));
}
return result;
}
};
注:本博文为EbowTang原创,后续可能继续更新本文。如果转载,请务必复制本条信息!
原文地址:http://blog.csdn.net/ebowtang/article/details/51658886
原作者博客:http://blog.csdn.net/ebowtang
本博客LeetCode题解索引:http://blog.csdn.net/ebowtang/article/details/50668895