给定正整数 N,返回小于等于 N 且具有至少 1 位重复数字的正整数的个数。
示例 1:
输入:20
输出:1
解释:具有至少 1 位重复数字的正数(<= 20)只有 11 。
示例 2:
输入:100
输出:10
解释:具有至少 1 位重复数字的正数(<= 100)有 11,22,33,44,55,66,77,88,99 和 100 。
示例 3:
输入:1000
输出:262
提示:
1 <= N <= 10^9
思路:这道题可以采用两种解法,一种是数位DP,直接套模板就ok,另一种是逆向思维,我们考虑数字的各个位上不存在重复数字的情况,这其实是很好统计的,我们可以详见代码:
class Solution {
public int numDupDigitsAtMostN(int N) {
String s=String.valueOf(N);
char[] c=s.toCharArray();
int n=c.length,total=0;
int[] flag=new int[10];
//数字位数小于n
for(int i=1;i<n;i++)
total+=9*C(9,i-1);
//数字位数等于n
for(int i=0;i<n;i++) {
int num=Integer.valueOf(c[i]+"");
for(int j=(i==0?1:0);j<num;j++) {
if(flag[j]!=0) continue;
total+=C(10-1-i,n-i-1);
}
if(++flag[num]>1) break;
if(i==n-1) total+=1;
}
return N-total;
}
private int C(int m,int n) {
return fact(m)/fact(m-n);
}
private int fact(int n) {
if(n<=1) return 1;
return n*fact(n-1);
}
}