一、题目描述
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, 10n) 中所有位数字都不相同的数共有多少个。
思路:一开始想到排列组合的解法去了,比如n=2时,在想区间[10, 100)中有多少个数不满足要求呢,只有两位比较好数,11,22,33,44,...,99共9个数.... 后来发现找出的规律根本就不对。看了提示才发现直接从正面入手比较简单,假设现在在求n位的数满足条件的个数(不考虑n位以下的数),对于第一位有9种可能(因为第一位不能为0,否则就不是n位数是n-1位数了),第二位可以为0,但是不能和第一位相同,所有有9种选择,第三位是8种选择.....这样,就找出规律了f(1) = 10, f(n) = 9 * 9 * 8 * ... * (9-n+2),然后把 f(1) 到 f(n) 加上即可。
c++代码(0ms,16.19%)
class Solution {
public:
int countNumbersWithUniqueDigits(int n) {
//1、当n=0时,区间[0,1)
if(n==0){
return 1;
}//if
//2、当n=1时,区间[0,10)
else if(n == 1){
return 10;
}//else if
//4、当n>=2时,此时要去掉有重复数字的整数了
else{
int result=91;
for(int i=3; i<=n; i++){
int tmp=9;
int flag=0;
int res=1;
for(int j=1;j<=i;j++){
res = res*tmp;
if(flag==0){
flag=1;
}else{
tmp--;
}
}//for
result+=res;
}//for
return result;
}
}
};思路和运行时间一样,简洁点的代码如下:
class Solution {
public:
int countNumbersWithUniqueDigits(int n) {
if(n==0) return 1;
if(n==1) return 10;
int val = 9, ans = 10;
for(int i = 2; i <= n; i++)
{
val *= (9-i+2);
ans += val;
}
return ans;
}
};代码2:
class Solution {
public:
int countNumbersWithUniqueDigits(int n) {
vector<int> dp(n+1, 0);
if(n==0)
return 1;
dp[0]=1;
for(int k=1;k<=n;k++){
int num=9;
int res=9;
for(int i=2;i<=k;i++){
res=res*num;
num--;
}
dp[k]=res+dp[k-1];
}//for
return dp[n];
}
};
本文介绍了一种高效算法,用于计算区间[0,10^n)内所有位数字都不相同的数的数量。通过递推公式f(n)=9*9*8*...*(9-n+2)进行计算,并提供两种C++实现方案。
1890

被折叠的 条评论
为什么被折叠?



