计算数字 k 在 0 到 n 中的出现的次数,k 可能是 0~9 的一个值。
样例 1:
输入: k = 1, n = 1 输出: 1 解释: 在 [0, 1] 中,我们发现 1 出现了 1 次 (1)。
样例 2:
输入: k = 1, n = 12 输出: 5
解释: 在 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,12] 中,我们发现 1 出现了 5 次 (1, 10, 11, 12)。
11里面有2个1 所以是5次
解题思路
首先 得找规律 假设n是123
当k是1时
个位带1的是 1 ,11 ,21 ,31 ,41 ,51 ,61 ,71 ,81 ,91
101 ,111 ,121
个位带1的一共13个
十位带1的是 10,11,12 ,13 ,14 ,15 ,16 ,17, 18 ,19
110,111,112,113,114,115,116,117,118,119
十位带1的一共20个
百位带1的是 100,101,102,103,104,105,106,107,108,109
110,111,112,113,114,115,116,117,118,119
120,121,122,123
百位带1的一共24个
所以0~123里面1出现了57次
当k是2时
个位带2的是 2 ,12 ,22 ,32 ,42,52 ,62 ,72 ,82 ,92
102 ,112 ,122
个位带1的一共13个
十位带2的是 20,21,22 ,23 ,24 ,25 ,26 ,27, 28 ,29
120,121,122,123
十位带1的一共14个
百位带1的是 一个没有
所以0~123里面2出现了27次
…
总结下来 比如n为123
k为1时 个位1出现 (123 / 10) * 1 + 1 = 13
十位1出现 ((123 / 10 ) / 10) * 10 + 10 = 20
百位1出现 (123%100)+1 = 24
k为2时 个位2出现 (123 / 10) * 1 + 1 = 13
十位2出现 ((123 / 10)/10) * 10 + (123%10)+1 = 14
…
继续总结 当 n为12345
k为3 个位为5 5>3 (12345 / 10) * 1 +1 = 1235
十位为4 4>3 ((12345/10)/10) * 10 + 10 = 1240
百位为3 3=3 (((12345/10)/10)/10) * 100 + (12345%100)+1 = 1246
千位为2 2<3 ((((12345/10)/10)/10)/10) * 1000 +0 = 1000
万位为1 1<3 最高位小于1 所以最高位存在0个
加起来 存在3的次数为4721次
那我们找到了规律
上面加粗部分是 每位必须有的
然后后面是加 他的位数 还是加(n % 位数)+ 1
是取决于当前位数 大于k还是 等于k 还是小于 k
在上面 我们找到了当k是1到9时的规律 然后开始找 k是0的规律
当n为12345 k是0时
k为3 个位 (12345 / 10) * 1 +1 = 1235
十位 ((12345/10)/10) * 10 = 1230
百位 (((12345/10)/10)/10) * 100 = 1200
千位 ((((12345/10)/10)/10)/10) * 1000 +0 = 1000
万位 最高位存在0个
加起来 存在0的次数为4665次
所以当k是0时 除了 个位多加了1 其他为 都直接取 (n/当前位数/10) * 当前位数
代码如下
public int digitCounts(int k, int n) {
if(k==0&&n<10){
return 1;
}
int m = n;
int count = 0;
int base = 1;
while(m>0){
int lastNum = m % 10;
m = m/10;
count = count + m*base;
//k大于0的情况
if(k>0){
if(lastNum == k){
count = count + (n % base)+1;
}else if(lastNum < k){
count = count + 0;
}else{
count = count + base;
}
//k为0的情况
}else{
if(lastNum>k&&base==1){
count = count + 1;
}
}
base = base * 10;
}
return count;
}