剑指 Offer 43. 1~n整数中1出现的次数
输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。
例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。
示例 1:
输入:n = 12
输出:5
示例 2:
输入:n = 13
输出:6
限制:
1 <= n < 2^31
暴力操作不可取,直接超时
class Solution:
def countDigitOne(self, n: int) -> int:
pre, cur = 0, 0
def solve(num):#计算当前数值的含1个数
cnt = 0
if num == 1: return 1
elif 1 < num <= 9: return 0
while num > 9:
num, b = divmod(num, 10)
if num == 1: cnt += 1
if b == 1: cnt += 1
return cnt
for i in range(1, n+1):
cur = pre + solve(i)
pre = cur
return cur
《编程之美》上这样说:
- 设N = abcde ,其中abcde分别为十进制中各位上的数字。
- 如果要计算百位上1出现的次数,它要受到3方面的影响:百位上的数字,百位以下(低位)的数字,百位以上(高位)的数字。
- 如果百位上数字为0,百位上可能出现1的次数由更高位决定。比如:12013,则可以知道百位出现1的情况可能是:100~199,1100 ~1199,2100 ~2199,,…,11100 ~11199,一共1200个。可以看出是由更高位数字(12)决定,并且等于更高位数字(12)乘以 当前位数(100)。注意:高位数字不包括当前位
- 如果百位上数字为1,百位上可能出现1的次数不仅受更高位影响还受低位影响。比如:12113,则可以知道百位受高位影响出现的情况是:100~ 199,1100~ 1199,2100~ 2199,,…,11100~ 11199,一共1200个。和上面情况一样,并且等于更高位数字(12)乘以 当前位数(100)。但同时它还受低位影响,百位出现1的情况是:12100~12113,一共14个,等于低位数字(13)+1。 注意:低位数字不包括当前数字
- 如果百位上数字大于1(2~ 9),则百位上出现1的情况仅由更高位决定,比如12213,则百位出现1的情况是:100~ 199,1100~ 1199,2100 ~ 2199,… 11100~ 11199,12100~12199,一共有1300个,并且等于更高位数字+1(12+1)乘以当前位数(100)。
根据上面的分析进行编程。首先由低位开始计算。
class Solution:
def countDigitOne(self, n: int) -> int:
cnt = 0
layer = 1#从最低位开始算
while n >= layer:
high = n // layer // 10 #高位
cur = n // layer % 10 #当前位
low = n - n // layer * layer #低位
if cur == 0:
cnt += high * layer
elif cur == 1:
cnt += high * layer + low + 1
else:
cnt += (high + 1) * layer
layer *= 10
return cnt