给定正整数 N,返回小于等于 N 且具有至少 1 位重复数字的正整数的个数。
示例 1:
输入:20
输出:1
解释:具有至少 1 位重复数字的正数(<= 20)只有 11 。
转化为求都不重复的正整数的个数
例如
3562
高位是0
4th 3th 2th 1th total
0 0 0 1-9 9xA(9,0)
0 0 1-9 0-9 9xA(9,1)
0 1-9 0-9 0-9 9xA(9,2)
高位不是0
4th 3th 2th 1th total
1-2 0-9 0-9 0-9 2xA(9,3)
3 0-4 0-9 0-9 5xA(8,2)
3 5 0-5 0-9 6xA(7,1)
3 5 6 0-1 2xA(6,0)
3 5 6 2 1
class Solution {
public:
int numDupDigitsAtMostN(int N) {
int len = 0;
int tmp = N;
vector<int> digits;
//计算位数
while(tmp)
{
len++;
digits.push_back(tmp%10);
tmp/=10;
}
//逆序排序
reverse(digits.begin(), digits.end());
vector<int> dp(len+1, 0);
//高位是0的情况
for(int i = 1;i <= len; i++)
{
int num = 9;
for(int j = 1;j < i; j++)
num *= (9 - j + 1);
dp[i] = num;
}
int cnt = 0;
for(int i = 1;i < len;i++) cnt += dp[i];
// 高位不是0
vector<int> vis(10, false);
for(int i = 0;i < len;i++)
{
int k = 0;
for(int j = (i == 0 ? 1 : 0);j < digits[i];j++)
{
if(vis[j] == false)
k++;
}
for(int j = i + 1;j < len;j++)
k *= (10 - j);
cnt += k;
if(vis[digits[i]])
break;
vis[digits[i]] = true;
if(i == len - 1) cnt++;
}
return N-cnt;
}
};