题目描述
求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。
主要思路都是在该题的讨论区里看到的。
我们这里以十位为例,不以百位为例了。
要根据十位数的这个数字分为几种情况,十位数字可能是0~9上的数字
就令i=10,a=n/i b=n%i
当十位为0的时候,那么假设n为303,a=30,b=3,那十位出现1的就是01x,11x,21x(x为0~9)一共三种,每种10次,一共是3*10=30次;如果n为2103,则a=210,b=3,那十位出现1的就是从01x,到201x一共21种,每种十次一共是21*10次,不明白可以多选几个n列出,这样就可以看出,当十位是0的时候,1出现的次数就只跟十位之前的高位数字有关。
n=303 考虑十位上1出现的次数,i=10
则 a=n/i=30 b=n%i=3
十位上1出现的次数有
01x (x从0~9共十个) 10次
11x 10次
21x 10次
总计30次
即只跟比十位高的位有关,高位从0~2 3个*10(共30次)
然后当十位是1的时候,这时候要注意31y的时候,不是十次,所以这种情况1的次数跟高位有关,也跟低位有关
n=313 i=10
a=n/i=31 b=n%i=3
此时十位上1出现的次数有
01x 10次
11x 10次
21x 10次
31y(这里是从0~3) 3+1次 (310,311,312,313)
总计30+(3+1)次
即此时跟比十位高的位有关,也跟比十位低的位有关
0~2 (3*10)次 + 0~3 (3+1)次
而当十位大于1(也就是2~9的时候)
n=333 i=10
a=n/i=33 b=n%i=3
此时十位上1出现的次数有
01x 10次
11x 10次
21x 10次
31x 10次
总计40次
即也是只跟高位有关,而这时高位从0~3 4*10 共40次
这样就是把十位上的数字分成了上面三种情况,总结下来就是
当十位是0时,只跟高位有关,共有(a/10)*10次
当十位是1时,既跟高位有关,又跟低位有关,共有(a/10)*10+(b+1)次
当十位是2~9时,也只跟高位有关,共有(a/10+1)*10次
同理,个位百位以及更高位也是这样。
class Solution {
public:
int NumberOf1Between1AndN_Solution(int n)
{
int count=0;
for(int i=1;i<=n;i*=10)
{
int a=n/i,b=n%i;
int now=a%10;
if(now==0)
count+=(a/10)*i;
else if(now==1)
count+=(a/10)*i+b+1;
else
count+=(a/10+1)*i;
}
return count;
}
};