LeetCode 233. Number of Digit One

来源:互联网 发布:mac怎么关闭icloud 编辑:程序博客网 时间:2024/05/18 02:46

原题网址: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
原创粉丝点击