劍指offer-31:整數中1出現的次數(從1到n整數中1出現的次數)

參考: https://troywu0.gitbooks.io/interview/整數中出現1的次數(從1到n整數中1出現的次數).htmlhtml

題目描述

求出1~13的整數中1出現的次數,並算出100~1300的整數中1出現的次數?爲此他特別數了一下1~13中包含1的數字有一、十、十一、十二、13所以共出現6次,可是對於後面問題他就沒轍了。ACMer但願大家幫幫他,並把問題更加廣泛化,能夠很快的求出任意非負整數區間中1出現的次數(從1 到 n 中1出現的次數)。
 

解題思路1 (暴力法,時間複雜度: O(nlog(n))

 1 public int NumberOf1Between1AndN_Solution(int n) {
 2     int count = 0;
 3     while (n > 0) {
 4         String nStr = String.valueOf(n);
 5         for (int i = 0; i < nStr.length(); i++) {
 6             if (nStr.charAt(i) == '1')
 7                 count++;
 8         }
 9         n--;
10     }
11     return count;
12 }

這種方法的思路簡單,統計每個數中出現1的次數,可以快速寫出代碼。可是,這種方法的時間複雜度很高,O(nlog(n)),面試這麼寫,估計不會留下好的印象。git

 

解題思路2 (數學規律法,時間複雜度: O(log(n))

 1 public int NumberOf1Between1AndN_Solution(int n) {
 2     int low = 0, cur = 0, high = 0;
 3     int count = 0;
 4     int factor = 1;
 5     while (factor <= n) {
 6         high = n / (factor * 10);
 7         low = n % factor;
 8 //            cur = (n - high * (factor * 10) - low) / factor;
 9         cur = (n / factor) % 10;
10         if (cur == 0)
11             count += high * factor;
12         else if (cur == 1)
13             count += high * factor + low + 1;
14         else
15             count += (high + 1) * factor;
16         factor *= 10;
17     }
18     return count;
19 }

這一個思路利用了數字的規律和特色,解決問題的效率很是的高,時間複雜度只與數的位數有關。面試

首先看一個規律:spa

  • 從1 - 10中,個位中 1 出現的次數是1,即1這個數;
  • 從1 - 100中,十位中 1 出現的次數是10, 即10, 11, ..., 18, 19;
  • 從1 - 1000中,百位中 1 出現的次數是100,即100, 101, ..., 198, 199;
  • 以此類推。

假設有一個四位數,使用 cur 來表示當前位數對應的數值,high表述cur左邊的數,low表示cur右邊的數。會有三種狀況產生:code

  • 第一種:cur = 0,1出現的次數等於 high * (該位數對應的基數)
    • 假設四位數爲1023,求百位上1出現的次數;
    • 此時 high = 1, cur = 0, low = 23;
    • 次數 = 1 * 100;
    • 即100, 101, ..., 198, 199。
  • 第二種:cur = 1,1出現的次數等於 high * (該位數對應的基數) + low + 1
    • 假設四位數爲1123,求百位上1出現的次數;
    • 此時 high = 1, cur = 1, low = 23;
    • 次數 = 1 * 100 + 23 + 1;
    • 即100, 101, ..., 198, 199  +  1100, 1101, ..., 1122, 1123。
  • 第三種:cur > 1,1出現的次數等於 (high + 1) * (該位數對應的基數)
    • 假設四位數爲1223,求百位上1出現的次數;
    • 此時 high = 1, cur = 2, low = 23;
    • 次數 = (1 + 1) * 100;
    • 即100, 101, ..., 198, 199  + 1100, 1101, ..., 1198, 1199。

根據這一規律,從最低位至最高位,依次求出1出現的次數,最後相加獲得最終的結果。htm

相關文章
相關標籤/搜索