解题思路:
首先最简单的方法一定是直接找出每个区间内的不同数字个数,因为n的取值只有8个,暴力点每个都算出来switch返回即可,代码如下:
class Solution {
public:
int countNumbersWithUniqueDigits(int n) {
switch (n) {
case 0: return 1;
case 1: return 10;
case 2: return 91;
case 3: return 739;
case 4: return 5275;
case 5: return 32491;
case 6: return 168571;
case 7: return 712891;
case 8: return 2345851;
case 9: return 5611771;
default : return 8877691;
}
return 0;
}
};
第二种方法是动态规划的方法,说是动态规划,其实也就是每次10k-1——10k区间的位不同数字个数与之前区间的统计加起来,每个区间的数字个数又和排列组合相关,比如一个四位数,那么第一位能取9个数(除了0),第二位能取9个数(除了第一位),第三位取8个数,最后一位取7个数,相乘起来就是该区间的各位数不同的个数了,代码如下:
class Solution {
public:
int countNumbersWithUniqueDigits(int n) {
if(n == 0) return 1;
vector<int> dp(n + 1);
dp[0] = 1;
dp[1] = 10;
for(int i = 2; i <= n; i ++) {
dp[i] = dp[i - 1] + (dp[i - 1] - dp[i - 2]) * (11 - i);
}
return dp[n];
}
};
第三种方法直接套用排列组合,在遍历的时候,一个变量存储当前总和,一个变量存储当前的排列组合规律(9*9*8*…*(n-1)),代码如下:
class Solution {
public:
int countNumbersWithUniqueDigits(int n) {
int res = 1;
int choose = 9;
for(int i = 1; i <= n; i ++) {
res += choose;
choose = choose * (10 - i);
}
return res;
}
};
最后一种方法可能大家也猜到了,就是递归的思路,这样短短三行代码就能实现,代码的思路本质上和排列组合相同,代码如下:
class Solution {
public:
int countNumbersWithUniqueDigits(int n) {
if(n == 0) return 1;
if(n == 1) return 10;
return countNumbersWithUniqueDigits(n - 1) + (countNumbersWithUniqueDigits(n - 1) - countNumbersWithUniqueDigits(n - 2)) * (11 - n);
}
};
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)