【LeetCode-數學】1~n整數中1出現的次數
阿新 • • 發佈:2020-07-25
題目描述
輸入一個整數 n ,求1~n這n個整數的十進位制表示中1出現的次數。
例如,輸入12,1~12這些整數中包含1 的數字有1、10、11和12,1一共出現了5次。
示例:
輸入:n = 12
輸出:5
輸入:n = 13
輸出:6
說明:
1 <= n < 2^31
題目連結: https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof/
思路
由於 n 的範圍非常大,所以暴力求解是行不通的。
假設 n 是 x 位數,第 i 位表示為 \(n_i\),所以 \(n=n_xn_{x-1}\dots n_1\)
- \(n_xn_{x-1}\dots n_{i+1}\) 被稱為高位 high;
- \(n_{i-1}n_{i-2}\dots n_1\) 被稱為地位 low;
- \(n_i\) 被稱為當前位 cur;
- 將 \(10^i\) 稱為位因子,記為 digit;
high、low、cur、digit 的初始化為:
int high = n/10;
int low = 0;
int cur = n%10;
long digit = 1; // long 型別,否則會溢位
high、low、cur、digit 的更新方法為:
low += cur*digit; cur = high%10; high /= 10; digit *= 10;
在每一步,我們根據 high、low、cur、digit 的情況來計算 1 的個數 ans,具體分 3 種情況:
- cur==0,此時 ans += high*digit;
- cur==1,此時 ans += hight*digit+low+1;
- cur==2~9 的情況,ans += (high+)*digit;
這篇題解舉了幾個例子來介紹為什麼要這麼做。
程式碼如下:
class Solution { public: int countDigitOne(int n) { int high = n/10; int low = 0; int cur = n%10; long digit = 1; // long 型別,否則會溢位 int ans = 0; while(high!=0 || cur!=0){ // 注意條件 if(cur==0) ans += high*digit; else if(cur==1) ans += high*digit+low+1; else ans += (high+1)*digit; low += cur*digit; cur = high%10; high /= 10; digit *= 10; } return ans; } };
- 時間複雜度:O(logn)
- 空間複雜度:O(1)
參考
https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof/