《劍指Offer》計算從1到n整數中1出現的次數

題目

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

PS:牛客鏈接LeetCode鏈接


方法一(Brute Force)

思路: 直接遍歷1~n之間的每個數字,每次循環使用先取餘(%10)後自除以10的方式,統計每個數字的各個數位上1出現的次數,並累加,然後返回總和

複雜度分析: 時間複雜度:O(n*logn),空間複雜度:O(1)

代碼:


方法二

思路: 將n的各個數位的值能夠在0~9之間任意變換組合。分別將各個數位設置成數字1,在保證整體值不大於n的情況下,觀察其他數位上的數的變化範圍,統計滿足條件的組合個數,即某個數位上值爲1的數字有多少個,最後將各個數位值爲1的情況下的組合個數求和即可。

舉例1:當n=2020時,計算其百位上爲1時的組合個數

當n=2020時,計算其百位上爲1時的組合個數


舉例2:當n=2120時,計算其百位上爲1時的組合個數

當n=2120時,計算其百位上爲1時的組合個數


舉例3:當n=2220時,計算其百位上爲1時的組合個數

當n=2220時,計算其百位上爲1時的組合個數


規律總結:

x爲數n的右邊起第i(i>=0)個數位上的數值,left爲n中第i位左側數字組成的值,right爲n中第i位的右側數字組成的值,則:

1. 當x==0時: 當前數位上值爲1的組合值個數爲left*10^i

2. 當x==1時: 當前數位上值爲1的組合值個數爲left*10^i+right+1

3. 當x>1時: 當前數位上值爲1的組合值個數爲(left+1)*10^i


舉例4:當n=2134時,計算1~n中數字1出現的次數

若n的個位爲1: 組合數爲214

若n的個位爲1時

若n的十位爲1: 組合數爲220

若n的十位爲1時

若n的百位爲1: 組合數爲200+35=255
若n的百位爲1:

若n的千位爲1: 組合數爲1000
若n的千位爲1

共計1669種組合,即在1~2134範圍內的整數中,1出現的次數爲1669次


本人代碼(Java):

public class Solution {
    public int countDigitOne(int n) {
        // 左側數值,當前數位的數值,右側數值
        long leftNum,curNum,rightNum;
        // 當前數位,數字1出現的次數
        long k = 1,count = 0;
        while(k<=n){
            leftNum = n/k/10;
            curNum = n/k%10;
            rightNum = n%k;
            if(curNum == 1) count += leftNum*k+rightNum+1;
            else if(curNum > 1) count += (leftNum+1)*k;
            else count += leftNum*k;
            k*=10;
        }
        return count;
    }
}

複雜度分析: 時間複雜度:O(logn),空間複雜度:O(1)


大神代碼(Java):

public int countDigitOne(int n) {
  int count = 0;
    
  for (long k = 1; k <= n; k *= 10) {
    long r = n / k, m = n % k;
    // sum up the count of ones on every place k
    count += (r + 8) / 10 * k + (r % 10 == 1 ? m + 1 : 0);
  }
    
  return count;
}

End~

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