1. 程式人生 > 其它 >動態規劃問題(五)數字1的個數

動態規劃問題(五)數字1的個數

動態規劃問題(五)數字1的個數

問題描述

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

​ 例如:對於整數 13,所有包含 1 的非負整數為 13、12、11、10、1 這些數裡面數字 1 總共出現了 6 次,因此得到的結果為 6.

解決思路

​ 按照分位數計算 1 出現的次數即可。比如說,對於 13,我們可以首先計算個位數 1 出現的次數,再統計十位數上的出現次數即可。

​ 一般來講,對於任意的一個整數 n,從個位開始依次計算每個位數 1 出現的次數,最終累加即可。

​ 比如說,對於百分位來講(如果 n 此時大於 100),那麼當前就會有 $\lfloor \frac {n}{1000} \rfloor$ 個百分位的 1 出現,因此此時就會有 $\lfloor \frac {n}{1000} \rfloor \times 100$ 個 1 出現(因為 100 本身自帶一個 1,因此對於任意的 100,101 .....) 都至少會有一個 1。而對於餘數部分,此時要分三種情況:

  • 餘數 < 100,那麼這種情況下在百分位的 1 就是 0,不要再考慮
  • 100 <= 餘數 < 200,此時只有 餘數 - 100 + 1 個百分位的 1,+ 1 是由於要包括 100
  • 餘數 >= 200,此時就會包含整個百分位的 1,因此這種情況下 1 的個數為 100

因此,對於當前n,再當前的百分位上包含的 1 的個數為:

​ $\lfloor \frac {n}{1000} \rfloor \times 100 + min(max(n \mod 1000 - 100 + 1, 0), 100)$​

對於一般的位數:

​ $\lfloor \frac {n}{10^{k+1}} \rfloor \times 10^k + min(max(n \mod 10^{k + 1} - 10^k + 1, 0), 10^k)$​

依次遍歷每個位數即可得到最終的結果。

實現

public class Solution {
    public static int countDigitOne(int n) {
        int ans     =   0;
        // 初始計算個位數的 1
        int digit   =   1;

        // 不斷迭代每個位數的 1,即可得到最終的結果
        while (digit <= n) {
            ans += (n / (digit * 10)) * digit
                    + Math.min(Math.max(n % (digit * 10) - digit + 1, 0), digit);

            digit *= 10;
        }

        return ans;
    }
}