首页 > 代码库 > Leetcode 233 Number of Digit One

Leetcode 233 Number of Digit One

1. 问题描写叙述

  给定一个整数n,在全部不大于n的非负整数中,计算包括数字1的整数的个数。比如n=13<script id="MathJax-Element-31" type="math/tex">n = 13</script>的结果为6。包括1的数字有1,10,11,12。13。


2. 方法与思路

  这个问题最直观的方法就是累加1到n全部的包括1的数的个数。每一个数通过循环取余10的方法推断是否包括1。可是这样的思路效率并不高,数字n有logn<script id="MathJax-Element-736" type="math/tex">logn</script>位。总得时间复杂度为O(nlogn)<script id="MathJax-Element-737" type="math/tex">O(nlogn)</script>。
  利用数字的规律,简化计算。以数字21567为例。先将数字分为两段:“1到1567”和“1568到21567”。
  从1568到21567这段,分为两种情况,1出如今最高位的情况。从10000到19999的数字中,包括1的一共出现了104<script id="MathJax-Element-738" type="math/tex">10 ^4</script>个,但对于数字12345,1出如今10000到12345的万位的个数就是2345+1=2346<script id="MathJax-Element-739" type="math/tex">2345+1=2346</script>次。

再看1出如今从1568到21567后4位的情况。

相同分成两段,1568到11568和11569到21568。每一段剩下的4位书中,设当中一位是1,其它三位能够是0~9之间的数,依据排列组合原理处理就可以。
  至于从1到1567利用递归就能够了。
  

class Solution {
private:
    int numofOne(int n)
    {
        if(n == 0) return 0;
        if(n > 0 && n < 10) return 1;

        int a = n,cnt = 0,num1,num2,num3;

        while(a/10)
        {
            a /=10;
            cnt++;
        }

        if(a > 1)
            num1 = pow(10,cnt);
        else if(a == 1)
            num1 = n%(int)pow(10,cnt)+1;

        num2 = a * (cnt)*pow(10,cnt-1);
        num3 = numofOne(n%(int)pow(10,cnt));

        return num1+num2+num3;

    }
public:
    int countDigitOne(int n) {
        return numofOne(n);
    }
};
<script type="text/javascript"> $(function () { $(‘pre.prettyprint code‘).each(function () { var lines = $(this).text().split(‘\n‘).length; var $numbering = $(‘
    ‘).addClass(‘pre-numbering‘).hide(); $(this).addClass(‘has-numbering‘).parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($(‘
  • ‘).text(i)); }; $numbering.fadeIn(1700); }); }); </script>

Leetcode 233 Number of Digit One