LeetCode 233. Number of Digit One

8 篇文章 0 订阅
3 篇文章 0 订阅

原题网址:https://leetcode.com/problems/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.

这道题需要注意的是统计的是十进制的1的个数,而不是二进制的1的个数!

思路:分别统计个位、十位、百位等各个数位上面1的个数,累加起来。

假定n=915,

我们先来看个位,个位从0~9,每一段10个数字,其中有一个1,所以我们将n除以10,计算出有多少段,因为n/10=91,所以个位上有91个1,但要注意这里是整除,漏掉了910~915这一段,所以要将n对10取模,得到5,然后5大于等于1,因此需要补上这个1.

然后来看十位,十位数从0~9,每一段有100个数字,其中有10个1,所以我们将n除以100再乘以10,就可以计算出1的个数(91个),同样注意漏掉了910~915这一段,包含有5个1(911~915),如何得到这一段1的个数呢?方法是915对100取模减去10再加1,得到6。注意小于0的情况,例如n=108,则n%100-10+1=-1,也就是最后一段的十位数小于1,不需要计算进去。

再看百位,每一段有1000个数字,其中有100个1,所以我们将n除以1000再乘以100,就是百位上1的个数(915/1000*100=0个),然后再计算最末一段的1的个数,方法是对915对1000取模减去100再加上1(915%1000-100+1=816个),注意这个816的含义,他表示100~915有816个数,但我们知道每一段最多只能有100个1,所以只需要取Math.min(816,100)即可。


public class Solution {
    public int countDigitOne(int n) {
        final int ONE_TENTH_OF_MAX_VALUE = Integer.MAX_VALUE / 10;
        int ones = 0;
        int m;
        for(m = 1; m <= n && m <= ONE_TENTH_OF_MAX_VALUE; m *= 10) {
            ones += n / (m * 10) * m;
            ones += Math.max(0, Math.min(n % (m * 10) - m + 1, m));
        }
        if (m <= n) ones += Math.max(0, Math.min(n - m + 1, m));
        return ones;
    }
}

一个简化的实现:

public class Solution {
    public int countDigitOne(int n) {
        int count = 0;
        for(long a = 10, b = 1; b <= n; a *= 10, b *= 10) {
            count += (int)(n / a * b + Math.max(0, Math.min(n % a - (b - 1), b)));
        }
        return count;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值