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.

分析

題意如下:給定一個非負整數n,輸出1,2,3,4,...,n這n個數中出現1的次數。

一開始的思路是遍歷從1到n這n個數,數出每個數中1的個數,時間復雜度O(nlogn)。看到較低的通過率,估計這種思路行不通。測試發現當n較大時會超時。代碼如下:

class Solution {
public:
    int countDigitOne(int n) {
        int count = 0;
        for (int i = 1; i <= n; ++i) {
            int num = i;
            while (num) {
                if (num % 10 == 1) {
                    ++count;
                }
                num /= 10;
            }
        }
        return count;
    }
};

因此換一種思路

先從中找規律。比如n=121。我們可以試圖逐位數出1的個數。

  • 首先是個位。
  • 1,11,21,31,41,51,61,71,81,91,101,111,121。不難發現是12+1個“個位”的1。
  • 十位。
  • 10,11,12,13,14,15,16,17,18,19,110,111,112,113,114,115,116,117,118,119。2*10個“十位”的1。
  • ...
  • 不難發現對于第i位。
  • 我們記數字n = a(m) * 10^m + a(m-1) * 10^(m-1) + ... + a(0) * 10^0
  • 并記p和q分別為第i位前的數和第i位后的數。
  • p = a(m) * 10^(m-i-1) + ... + a(i+1) * 10^0
  • q = a(i-1) * 10^(i-1) + ... + a(0) * 1
  • 再記第i位數字為k。
  • 第i位的1的個數:p * 10^(i-1) + if (k == 1) { (q+1); } + if (k > 1) { 10^(i-1); }
  • 如數字83121=8 * 10000 + 3 * 1000 + 1*100 + 2 * 10 + 1 * 1, 對第三位(第三位為1)有p=83,q=21,k=1。第3位的1的個數為83 * 100 + 21 + 1 = 8322
  • 不難發現時間復雜度為O(logn)

AC代碼

class Solution {
public:
    int countDigitOne(int n) {
        int count = 0, previous = 0, coef = 1;
        while (n) {
            int remain = n % 10;
            int over = n / 10;
            if (remain > 1) {
                count += coef;
            } else if (remain == 1) {
                count += previous + 1;
            }
            count += coef * over;
            previous += coef * remain;
            coef *= 10;
            n /= 10;
        }
        return count;
    }
};
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容