leetcode 357. 计算各个位数不同的数字个数(DFS,回溯,数学)
题目链接
题意:
给定一个非负整数 n,计算各位数字都不同的数字 x 的个数,其中 0 ≤ x < 10n 。
示例:
输入: 2
输出: 91
解释: 答案应为除去 11,22,33,44,55,66,77,88,99 外,在 [0,100) 区间内的所有数字。
思路
-
法1:DFS+回溯
前导0单独处理,其余位置按0~9顺序每次插入,用一个数组vis[10]记录已经用过的数字 -
法2:数学
设f[i]表示i位数的有效数字,比如f[1]=10,f[2]=9*9,f[3]=9*9*8,以此类推,f[i]=f[10](i>10),10个以上的数字必定重复
最后结果就是f[1]+...+f[n](n<=10)或者f[1]+...+f[10]
特判:n=0时,f[0]=1
class Solution {
public:
//法2:
int countNumbersWithUniqueDigits(int n){
if(n==0) return 1;
vector<int> f(10,0);
f[1]=10;
f[2]=9*9;
for(int k=3;k<=10 && k<=n;k++){
f[k]=f[k-1]*(10-k+1);
}
int ans=0;
for(int i=1;i<=n&& i<=10;i++) ans+=f[i];
return ans;
}
//法1 :注意前导0
// int dfs(int n,vector<int> vis,int d){
// if(n==d) return 1;
// int ans=1;//前导0的情况
// for(int i=(d==0?1:0);i<=9;i++){
// if(vis[i]) continue;
// vis[i]=1;
// ans+=dfs(n,vis,d+1);
// vis[i]=0;
// }
// return ans;
// }
// int countNumbersWithUniqueDigits(int n) {
// if(n>=10) n=10;
// vector<int> vis(10,0);
// return dfs(n,vis,0);
// // if(n>1) ans+=1;
// // dfs(0,n);
// // return ans;
// }
};