1. 程式人生 > >233. 數字1的個數

233. 數字1的個數

給定一個整數 n,計算所有小於等於 n 的非負整數中數字 1 出現的個數。

示例:

輸入: 13
輸出: 6 
解釋: 數字 1 出現在以下數字中: 1, 10, 11, 12, 13 。

解題思路:
1.參考:https://www.cnblogs.com/grandyang/p/4629032.html
通過上面的列舉我們可以發現,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’。

程式碼:
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;
    }
};

 

對於(x+8)/10的理解:考慮res += (n + 8) / 10 * a + (n % 10 == 1) * b; n>=2和n<2會造成一個a的區別,a可以理解為個位、十分位、百分位等上1的個數,所以結合上面的描述,就是說尾數>=2的時候,就會有額外的1出現。關於這塊可結合下面的解法。


2.參考:https://blog.csdn.net/geekmanong/article/details/51050854
利用數學歸納法,直接對n進行分析,歸納總結規律

例如n=abcde五位數,我們分析百位的c,主要有以下三種情況:

1)當c == 0的時候,比如13013,此時百位出現1的是:00 100 ~ 00 199, 01 100~01 199,……,11 100~ 11 199,12100~12199共1300個,顯然這個由高位數字決定,並且受當前位數影響,結果為:(高位數字)乘以(當前位數);
2)當c == 1的時候,比如13113,此時百位出現1的肯定包括c=0的情況,另外還需要考慮低位的情況即:00100 ~ 00113共114個,結果為:(高位數字)乘以(當前位數)+(低位數字)+1;
3)當c >= 2的時候,比如13213,此時百位出現1的是:00 100 ~ 00 199, 01 100~01 199,……,11 100~ 11 199,12 100 ~ 12 199,13100~13199,共1400個,這個僅由高位數字決定,結果為:(高位數字+1)乘以當前位數。

程式碼:
class Solution {
public:
    int countDigitOne(int n) {
        if (n <= 0)  return 0;
        long count = 0;
        long factor = 1;
 
        while (n / factor)
        {
            long lower = n%factor;
            long cur = (n / factor) % 10;
            long higher = n / (factor * 10);
 
            switch (cur)
            {
            case 0:
                count += higher*factor;
                break;
            case 1:
                count += higher*factor + lower + 1;
                break;
            default:
                count += (higher + 1)*factor;
            }
            factor *= 10;
        }
        return (int)count;
    }
};