方法一:
抛开前导零考虑,只要0不是首位,则0与其他数字无异,
所以通过数字长度划分每种情况:
长度为1,第一位可以取0~10,共10种。
长度为2,必须为两位数,则第一位可以取1~9,第二位可以取剩下9种(这时可以取0),9*9共81种。
长度为3,9*9*8。
以此类推。
最后求和即可。
class Solution {
public:
int countNumbersWithUniqueDigits(int n) {
if(n==0) return 1;
int ans = 10;
int now = 9;
int key = 9;
for(int i = 1;i<n;i++){
now *= key;
ans += now;
key --;
}
return ans;
}
};
方法二:
状态转移思路:比较麻烦,通过n位数量来求出n+1位的数量。
如图,每个树分支上权值乘积,再分支求和即是答案。
简单说说这颗二叉树是如何构造的,
靠上的权值是当前位可以取1~9中数的个数,
靠下的权值是当前位取0的个数,
如果出现中间0,则之后不可再分裂。

class Solution {
public:
// n所求树高,level当前树层数,now当前树节点值,flag是否会出现中间0
int dfs(const int n,int level,int now,bool flag){
if(level == n) return now;
if(flag){
int sum = 1;
int key = now;
for(int i=level;i<n;i++){
sum *= key;
key--;
}
return sum + now*dfs(n,level+1,now-1,true);
}
return dfs(n,level+1,9,true) + dfs(n,level+1,1,false);
}
int countNumbersWithUniqueDigits(int n) {
return dfs(n,0,1,false);
}
};
本文探讨了两种高效算法,用于计算在特定长度下由不重复数字构成的数的总数。第一种方法通过数字长度划分,利用递推公式快速得出结果;第二种方法采用状态转移思想,构建树形结构辅助计算,适用于更复杂场景。文章深入解析算法细节,为解决类似问题提供新思路。
331

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



