剑指offer31 ——整数中1出现的次数(从1到n整数中1出现的次数)

剑指offer31 ——整数中1出现的次数(从1到n整数中1出现的次数)

求出113的整数中1出现的次数,并算出1001300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。

这道题抛开暴力解法不提是真的难,至少对我来说
做这道题首先要知道的“常识”:
1~10的个位1出现的次数是1
1~100的十位1出现的次数是10
1~1000的百位1出现的次数是100
1~10000的千位1出现的次数是1000

比如20个位数1出现的次数是20/10=2,(1,11)
当然这是整数好说,如果是21,22,23的话就是20/10+1=3(1,11,21),就是说如果不是正好的话,还要分情况
下面举例子:(1)125,105,115这三个数求它的十位出现的1的次数,先121/100=1,有1个100,根据上面的“常识”,只看整数的话它有1*10个。
(2)再看余数超过等于20的肯定有10~19十位出现1,共10个,比如125就是这样。如果余数超过等于10并且小于20的要看十位后面的数,比如115,就有10 ~15共5+1=6。最后看余数小于10的,也就是上面剩下的,比如105,十位为1个数为0。
最后把(1)(2)部分相加就是数的十位出现1的次数。
其他百位、千位的都是同理。

class Solution {
public:
    int NumberOf1Between1AndN_Solution(int n)
    {
        int count=0;
        for(int i=1;i<=n;i*=10)
        {
            count+=n/(i*10)*i;    //求i位整除部分的1的次数(算十位时125/100有一个100,要乘10)
            if(n%(i*10)>=2*i)    //i位余数部分是否>=2*i,如果是则是固定的i(125)
            {
                count+=i;
            }
            else if(n%(i*10)>=i)    //如果不是且>=i,则看i位以后的所有位数,+1表示本身(115十位的10)
            {
                count+=n%(i*10)%i+1;
            }
                                        //剩下的十位一定没有(105)
        }
        return count;
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值