题目:
输入一个整数 n, 求 1 ~ n 这 n 个整数的十进制表示中 1 出现的次数.
问题分析:
当
n
是最大的
任何一位上的数字都可以是
0∼9
(位数不足的在前面补
0
, 如四位数的
则
故有
为了讨论的方便, 将
n
记为
则可得
案例:
n=10531
计算过程
个位数 1 :
sum(11)=1∗(1−1)∗h(1−1)+nmodh(1)11=1+1=0+0+1=1
;
十位数 3 :
sum(32)=3∗(2−1)∗h(2−1)+h(2)32>1=3+10=13
;
百位数 5 :
sum(53)=5∗(3−1)∗h(3−1)+h(3)53>1=100+100=200
;
千位数 0 :
sum(04)=0∗(4−1)∗h(4−1)+004=0=0+0=0
万位数 1 :
sum(15)=1∗(5−1)∗h(5−1)+nmodh(5)15=1+1=4000+531+1=4532
则 sum(n) 如下:
根据上述思想及公式, C++代码实现如下:
long NumberOf1(const int n)
{
long sum = 0;
int m = n;
for (int k = 0, hk = 1; m > 0; ++k)
{
int modK = m % 10;
sum = modK * k * (hk / 10);
if (modK == 1)
sum += n % hk + 1;
else if (modK > 1)
sum += hk;
m /= 10;
hk *= 10;
}
return sum;
}
该算法的时间复杂度为 O(logN), 空间复杂度为 O(1).