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