剑指offer-整数中1出现的次数

题目描述

求出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;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值