【劍指 2】面試題 43:1~n 整數中 1 出現的次數

題目:輸入一個整數 n,求 1~n 這 n 個整數的十進制表示中 1 出現的次數。例如,輸入 12,1~12 這些整數中包含 1 的數字有 1、10、11 和 12,1 一共出現了 5 此。

對於 X ∈ [1, 9],1~n 整數中 X 出現的次數在算法一樣。(0 的比較特殊,不過大致思想類似)。


解題思路:

分別以 12493、12593、12693 爲例,計算數字 5 出現的次數。

其中,結果爲 5 分別在個位、十位,直到萬位出現的次數的和。

以 5 在百位上出現的次數爲例進行講解:

  1. 對於 12493,百位上位爲 4 < 5,所以其更高位,即萬、千位只能從 00 - 11 進行變換,即 01、02...10、11 進行變化,共 12 種;而其更低位,即十、個位只能從 00 - 99 進行變換(因爲萬千位最大也才 11,即 115XX,此時十個位最大可爲 99,即 11599,小於 12493),共 100 種。

    因此,對於 12493,5 在百位出現的次數位 12 * 100 = 1200

  2. 對於 12593,百位上爲 5 == 5。所以其更高位,即萬、千位只能從 00 - 12 進行變換;而其更低位,就需要看情況了:
    (1)當萬千位爲 00 - 11 的時候,百十位可以是 00 - 99 進行變換;
    (2)當萬千位爲 12 的時候,因爲不能大過 12593,因此只能從 00 - 93 進行變換,共 94 種。

    因此,對於 12493,5 在百位出現的次數位 12 * 100 + 94 = 1294

  3. 對於 12693,百位上爲 6 > 5。所以其更高位,即萬、千位能從 00 - 12 進行變換,共 13 種;而其更低位,即十、個位能從 00 - 99 進行變換(因爲萬千位最大也才 12,即 125XX,此時十個位最大可爲 99,即 12599,小於 12693),共 100 種。

    因此,對於 12693,5 在百位出現的次數位 13 * 100 = 1300

對於 5 在其他位上出現的次數,也類似。


算法的具體實現:

// 用於控制數字 X 出現的次數
private static int X = 1;

public int NumberOf1Between1AndN_Solution(int n) {
    if (n < 1) return 0;
    if (n < 10) return 1;
    int sum = 0;
    // 用於輔助判斷是不是把 n 的每一位遍歷完了
    int tag = n;
    // 用於記錄位的索引,從 n 的個位向高位開始
    int index = 1;
    while (tag > 0) {
        int mi = (int) Math.pow(10, index);
        int num = n % mi;
        // 得到當前位的更高位
        int high = n / mi;
        int mi2 = (mi / 10);
        // 得到當前位
        int cur = num / mi2;
        // 得到當前位的更地位
        int low = num % mi2;
        // 記錄當前位出現 X 的次數
        int count = 0;
        if (cur < X) {
            count = high * mi2;
        } else if (cur > X) {
            count = (high + 1) * mi2;
        } else {
            count = high * mi2 + (low + 1);
        }
        tag /= 10;
        ++index;
        System.out.println(count);
        sum += count;
    }
    return sum;
}

一個數 n 有 ((O(log10 n) 取整) + 1) 位,因此上述算法的時間複雜度爲 O(log10 n )。

爲什麼數 n 有 ((O(log10 n) 取整) + 1) 位?

因爲假設 n ∈ [10x, 10x+1-1],且 n 爲整數,則 n 對於的位數屬於 x + 1。例如 199,其屬於 [100, 999],有 log10 100 = 2,則 199 對應的位數爲 2 + 1 = 3.


參考文章:劍指offer-整數中1出現的次數(從1到n整數中1出現的次數)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章