Given an integer n, count the total number of digit 1 appearing in all non-negative integers less than or equal to n.
Example:
Input: 13 Output: 6 Explanation: Digit 1 occurred in the following numbers: 1, 10, 11, 12, 13.
题目求1-n中1出现的数量。
比较容易计算10^n - 1的1的数量,规则如下:
countDigitOne(9) = 1
countDigitOne(99) = countDigitOne(9) *10 + 10
countDigitOne(999) = countDigitOne(99) *10 + 100
countDigitOne(9999) = countDigitOne(999) *10 + 1000
我们可以将1的个数分为3各部分:
- 最高位1的个数
- 整数部分1的个数
- 零头部分1的个数
代码如下:
class Solution(object):
def countDigitOne(self, n):
"""
:type n: int
:rtype: int
"""
if n < 0:
return 0
if n <= 10:
return [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2][n]
intStr = str(n)
l = len(intStr)
fn = intStr[0]
n1 = min(pow(10, l - 1), n - pow(10,l-1) + 1) # 第一位是1时,增加 n - pow(10,l-1) + 1个1,否者增加pow(10, l - 1)个1
n2 = ((l - 1) * pow(10, l - 2)) * int(fn) # 整数值,1的个数
n3 = self.countDigitOne(int(intStr[1:])) # 零头值的1的个数
return n1 + n2 + n3
优化一下,代码如下:
int countDigitOne(int n) {
long long int m = 1;
long long int ret = 0;
long long int a = 0;
while( m <= n){
int right_num = n%m;
int left_num = n/m;
int pos_num = left_num % 10;
if(pos_num == 1){
ret += (right_num+1) + a*(pos_num);
}else if(pos_num != 0){
ret += m + a*(pos_num);
}
a = 10*a + m;
m *= 10;
}
return ret;
}