问题描述
统计[0, 1, 2, … , n]中k出现的次数,其中k为0-9任意数.
分析
最笨的方法就是for
循环每个数,进行叠加计算,方法如下:
int digitCounts(int k, int n) {
int sum = 0;
for (int i = 0; i <= n; i++) { //循环每一个数
int num = i;
while (num / 10 != 0) { //判断数是否为0,做while循环
if (num % 10 == k) { //判断各位上的值是否为k,进行++
sum++;
num /= 10;
}
}
if (num == k) { //判断最高位的值是否为k,进行++
sum++;
}
}
return sum;
}
这样的做法,需要循环n次,还不包括内部的while循环,时间复杂度为O(n)
优化解法
例如:当n=12345
,固定一位,假设固定位为百位.
假设
- 当
k=4
即3<k
,百位上的数小于k
时.固定百位上的数是4
,则存在的数就是400-499
,1400-1499
,2400-2499
,…,10400-10499
,11400-11499
,即出现12x100
次,也就是高位数字x位数. - 当
k=3
即3=k
,百位上的数等于k
时.固定百位上的数是3
,则存在的数就是300-399
,1300-1399
,2300-1399
,…,10300-10399
,11300-11399
,还要包括12300-12345
这写数字.也就是高位数字x位数+低位数字+1. - 当
k=2
时,即3>k
,百位上的数大于k
时.固定百位上的数是2
,则存在的数就是200-299
,1200-1299
,…,10200-10299
,11200-11299
,12200-12299
.也就是**(高位数字+1)x低位数字**.
同理可以的到个位,十位,千位,万位的统计数字.
特别需要关注的是最高位上,如果k=0
时,最高位上不能为0
,排除这种情况.
因此优化代码:
int digitCounts(int k, int n) {
if (k == 0 && n < 10) { //排除k为0,n为个位数的情况
return 1;
}
int temp = n;
int count = 0;
int pow = 1; //位数
while (temp != 0) { //不为0时一直循环
int digit = temp % 10; //获取位数上的数
if (digit < k) { //进行比较
count += (temp / 10) * pow; //高位数字*位数
} else if (digit == k) {
count += (temp / 10) * pow + (n - temp * pow + 1); //高位数字*位数+低位数字+1
} else {
if (!(k == 0 && temp / 10 == 0)) { //排除k=0,计算最高位时的情况
count += (temp / 10 + 1) * pow; //(高位数字+1)*位数
}
}
temp /= 10; //退一位
pow *= 10; //进一位
}
return count;
}