[LeetCode] 233. Number of Digit One 數字1的個數


 

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.

 

這道題讓我們比給定數小的所有數中1出現的個數,之前有道類似的題 Number of 1 Bits,那道題是求轉為二進數后1的個數,博主開始以為這道題也是要用那題的方法,其實不是的,這題實際上相當於一道找規律的題。那么為了找出規律,我們就先來列舉下所有含1的數字,並每10個統計下個數,如下所示:

1的個數          含1的數字                                                                        數字范圍

1                   1                                                                                     [1, 9]

11                 111  111111119                              [10, 19]

1                   21                                                                                   [20, 29]

1                   31                                                                                   [30, 39]

1                   41                                                                                   [40, 49]

1                   51                                                                                   [50, 59]

1                   61                                                                                   [60, 69]

1                   71                                                                                   [70, 79]

1                   8                                                                                  [80, 89]

1                   91                                                                                   [90, 99]

11                 100  101  102  103  104  105  106  107  108  109          [100, 109]

21                 11111  11111111111111119             [110, 119]

11                 120  121  122  123  124  125  126  127  128  129          [120, 129]

...                  ...                                                                                  ...

 

通過上面的列舉可以發現,100 以內的數字,除了10-19之間有 11 個 ‘1’ 之外,其余都只有1個。如果不考慮 [10, 19] 區間上那多出來的 10 個 ‘1’ 的話,那么在對任意一個兩位數,十位數上的數字(加1)就代表1出現的個數,這時候再把多出的 10 個加上即可。比如 56 就有 (5+1)+10=16 個。如何知道是否要加上多出的 10 個呢,就要看十位上的數字是否大於等於2,是的話就要加上多余的 10 個 '1'。那么就可以用 (x+8)/10 來判斷一個數是否大於等於2。對於三位數區間 [100, 199] 內的數也是一樣,除了 [110, 119] 之間多出的10個數之外,共 21 個 ‘1’,其余的每 10 個數的區間都只有 11 個 ‘1’,所以 [100, 199] 內共有 21 + 11 * 9 = 120 個 ‘1’。那么現在想想 [0, 999] 區間內 ‘1’ 的個數怎么求?根據前面的結果,[0, 99] 內共有 20 個,[100, 199] 內共有 120 個,而其他每 100 個數內 ‘1’ 的個數也應該符合之前的規律,即也是 20 個,那么總共就有 120 + 20 * 9 = 300 個 ‘1’。那么還是可以用相同的方法來判斷並累加1的個數,參見代碼如下:

 

解法一:

class Solution {
public:
    int countDigitOne(int n) {
        int res = 0, a = 1, b = 1;
        while (n > 0) {
            res += (n + 8) / 10 * a + (n % 10 == 1) * b;
            b += n % 10 * a;
            a *= 10;
            n /= 10;
        }
        return res;
    }
};

 

解法二:

class Solution {
public:
    int countDigitOne(int n) {
        int res = 0;
        for (long k = 1; k <= n; k *= 10) {
            long r = n / k, m = n % k;
            res += (r + 8) / 10 * k + (r % 10 == 1 ? m + 1 : 0);
        }
        return res;
    }
};

 

Github 同步地址:

https://github.com/grandyang/leetcode/issues/233

 

類似題目:

Factorial Trailing Zeroes

Digit Count in Range

 

參考資料:

https://leetcode.com/problems/number-of-digit-one/

https://leetcode.com/problems/number-of-digit-one/discuss/64390/AC-short-Java-solution

https://leetcode.com/problems/number-of-digit-one/discuss/64381/4+-lines-O(log-n)-C++JavaPython

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM