[leetcode] 233. Number of Digit One

Given an integer n, count the total number of digit 1 appearing in all non-negative integers less than or equal to n.

For example:

Given n = 13,
Return 6, because digit 1 occurred in the following numbers: 1, 10, 11, 12, 13.

Hint:

  1. Beware of overflow.

这道题和数字有关,找出n以内数字中包含多少个1,题目难度为Medium。

假如n=9999,我们针对每一位进行统计,很容易看出0000~9999所有数字中,个位上每10个数字出现1个1,十位上每100个数字出现10个1,百位上每1000个数字出现100个1,等等。再以21045为例,个位上有多少个1出现呢?根据上面的分析,我们知道00000~21040所有数字中个位上共有2104个1(每10个数字出现1个1),而21041~21045所有数字中个位上只有1个1,个位就统计完了。十位上,00000~21000所有数字中十位上共有210*10个1(每100个数字出现10个1),而21001~21045所有数字中十位上共有10个1,十位也统计完了。百位上,00000~21000所有数字中百位上共有21*100个1(每1000个数字出现100个1),而21000~21045所有数字中百位上共有0个1,这里与个位和十位不同,因为百位是0,所以这段区间百位上不会有1。我们再看千位,00000~20000所有数字中千位上共有2*1000个1(每10000个数字出现1000个1),而20001~21045所有数字中千位共有46个1,这里与前面三者都不同,因为千位是1,所以这段区间上只有21000~21045上千位是1。

例子说到这里,相信大家已经想出了解决办法,根据每位上的数字来区别处理,0,1和大于1都是不同的。具体代码:

class Solution {
public:
    int countDigitOne(int n) {
        if(n <= 0) return 0;
        
        long long cnt = 0;
        long long wgt = 1;
        long long num = n;
        
        while(num > wgt/10) {
            long long quo = num / (wgt*10);
            long long rmd = num % (wgt*10);
            cnt += quo*wgt;
            if(rmd/wgt > 1) cnt += wgt;
            else if(rmd/wgt == 1) cnt += (rmd%wgt)+1;
            wgt *= 10;
        }
        
        return cnt;
    }
};

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值