Given an integer n, count the total number of digit 1 appearing in all non-negative integers less than or equal to n.
For example:
Given n = 13,
Return 6, because digit 1 occurred in the following numbers: 1, 10, 11, 12, 13.
分析
題意如下:給定一個非負整數n,輸出1,2,3,4,...,n
這n個數中出現1的次數。
一開始的思路是遍歷從1到n這n個數,數出每個數中1的個數,時間復雜度O(nlogn)
。看到較低的通過率,估計這種思路行不通。測試發現當n較大時會超時。代碼如下:
class Solution {
public:
int countDigitOne(int n) {
int count = 0;
for (int i = 1; i <= n; ++i) {
int num = i;
while (num) {
if (num % 10 == 1) {
++count;
}
num /= 10;
}
}
return count;
}
};
因此換一種思路:
先從中找規律。比如n=121
。我們可以試圖逐位數出1的個數。
- 首先是個位。
-
1,11,21,31,41,51,61,71,81,91,101,111,121
。不難發現是12+1個“個位”的1。 - 十位。
-
10,11,12,13,14,15,16,17,18,19,110,111,112,113,114,115,116,117,118,119
。2*10個“十位”的1。 - ...
- 不難發現對于第i位。
- 我們記數字
n = a(m) * 10^m + a(m-1) * 10^(m-1) + ... + a(0) * 10^0
。 - 并記p和q分別為第i位前的數和第i位后的數。
-
p = a(m) * 10^(m-i-1) + ... + a(i+1) * 10^0
。 -
q = a(i-1) * 10^(i-1) + ... + a(0) * 1
。 - 再記第i位數字為k。
- 第i位的1的個數:p * 10^(i-1) + if (k == 1) { (q+1); } + if (k > 1) { 10^(i-1); }
- 如數字
83121=8 * 10000 + 3 * 1000 + 1*100 + 2 * 10 + 1 * 1
, 對第三位(第三位為1)有p=83,q=21,k=1。第3位的1的個數為83 * 100 + 21 + 1 = 8322
。 - 不難發現時間復雜度為
O(logn)
。
AC代碼
class Solution {
public:
int countDigitOne(int n) {
int count = 0, previous = 0, coef = 1;
while (n) {
int remain = n % 10;
int over = n / 10;
if (remain > 1) {
count += coef;
} else if (remain == 1) {
count += previous + 1;
}
count += coef * over;
previous += coef * remain;
coef *= 10;
n /= 10;
}
return count;
}
};