这个问题困扰了我很久,现在终于是将问题理清了,如果拿这个问题去问一个中学生,他肯定是要比我算的要快的多,工作时间久了,求解数学的能力下降了也,当然对一些算法大神这个问题是不存在的,下面讲一下我的求解过程:
直接暴力循环使用正则匹配,然后累加,这应该是最容易想到的了(对我),这里就不在赘述这种方法了
解:
1、1~10之间,出现x的次数为1
2、1~100之间,十位出现x的次数为10
3、1~1000之间,百位出现x的次数为100
4、... ...依次类推,当1~10n之间,n位数出现x的次数为10(n-1)
1~3693之间出现6的次数
parseInt(3693/10) = 369所以总共有369个10,1~3690之间个位总共出现了369*1次6,来看剩余的3690~3693之间,因为个位数3<6,所以这之间不含有6, 1~3693之间的个位数总共出现了369次6
接下来看十位数,
parseInt(3693/100) = 36所以总共含有36个100,1~3600之间十位总共出现了36*10=360次6,来看剩余的3600~3693,这之间十位数为9,所以十位出现整10次6,1~3693之间的十位数总共出现了(36+1)*10 = 370次6
接下来看百位数
parseInt(3693/1000) = 3所以总共含有了3个1000,1~3693之间百位数出现了3*100=300次6,来看剩余的3000~3693,这之间因为百位数为6 === 6,这种情况就相对来说复杂了一下,这其中的百位数肯定是出现了6 从3600~3693,总共出现了(3693-3600+1)=94次6,1~3693之间的百位数总共出现了300+94=394次6
因为最大位数上的数字是3 < 6,所以最大位数(也即是千位)上不会出现6
至此我们可以得出,1~3693之间出现6的次数为369+370+394=1133次6
我们将以上的过程翻译成代码来实现
function countNum (n, x) {
var count = 0
var base = 1
var next = parseInt(n/base)
var curr, lower, high
while(next !== 0) {
high = parseInt(n / (base * 10))
curr = next % 10
if (curr < x) {
count += high * base
} else if (curr === x) {
lower = n - base * next
count += high * base + lower + 1
} else {
count += (high + 1) * base
}
base *= 10
next = parseInt(n / base)
}
return count
}