描述
输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数
例如,1~13中包含1的数字有1、10、11、12、13因此共出现6次
好多题解都看不懂呀,暴力解法肯定不太行,有可能n太大。
先来看看讨论组的数学归纳法:https://blog.nowcoder.net/n/562472a7292842dbb320d827b1a94031?f=comment
另外讨论组提供的Python代码:(困扰,看会视频再来)
# -*- coding:utf-8 -*-
class Solution:
def countDigitOne(self, n):
"""
:type n: int
:rtype: int
例:对于824883294,先求0-800000000之间(不包括800000000)的,再求0-24883294之间的。
如果等于1,如1244444,先求0-1000000之间,再求1000000-1244444,
那么只需要加上244444+1,再求0-244444之间的1
如果大于1,例:0-800000000之间1的个数为8个100000000的1的个数加上100000000,
因为从1000000000-200000000共有1000000000个数且最高位都为1。
对于最后一位数,如果大于1,直接加上1即可。
"""
result = 0
if n < 0:
return 0
length = len(str(n))
listN = list(str(n))
for i, v in enumerate(listN):
a = length - i - 1 # a为10的幂
if i==length-1 and int(v)>=1:
result+=1
break
if int(v) > 1:
result += int(10 ** a * a / 10) * int(v) + 10**a
if int(v) == 1:
result += (int(10 ** a * a / 10) + int("".join(listN[i+1:])) + 1)
return result
姚青林老师的视频讲解:https://www.bilibili.com/video/BV1K4411o7KP?p=28
假设要算1~3459082190:
①假如对于0这一位,它这时是0,如果要让它变成1呢?(0的情况)
先看前面部分,让0这一位往前面借1,所以前面只有3458,前面这四个数可以从0变化到3458(有3459变化次数),因为如果借了1,此时就算前面是3458,那么34581也是比34590要小的。
这时候看后面,因为此时0这一位变成1,所以后面每一位数都可以从0变化到9,所以总次数为,所以综上所述,除了0这一位的变化,其他位的变化总次数为。
②假如对于8这一位,它这时是8,那么要让他变成1呢?(比1大的情况)
因为这一位是8,所以不需要向前面借位,所以前面的34590可以从0到34590(有34591变化次数),因为34591也比34598小。
这时候加上后面的变化次数,所以其他位的变化总次数为.
③假如对于1这一位,它这时等于1怎么办呢?(本身为1的情况)
前面部分依旧是从0变化到3459082(有3459083变化次数),那这个时候后面呢?
因为如果这个数本身就是1,等于说不能超过后面数字的区间,因为如果是······191就超出了我们这个n的数。
所以后面的变化次数为90,即其他位的变化总次数为。
但是后面要是90以后的91,92,93···
这个时候等于说1这一位的1是需要往前面借一位得到的,所以就是前面的变化次数乘后面的变化次数。
综上所述,其他位的变化总次数为。
所以按照这三种情况,把所有位数的for循环写出来!
class Solution:
def NumberOf1Between1AndN_Solution(self, n):
if n == 1:
return n
#循环的出口
precise = 1
highValue = 1
midValue = 1
lowValue = 1
count = 0
sumNum = 0
while highValue != 0:
highValue = n//(precise*10)
midValue = (n//precise)%10
lowValue = n % precise
precise = precise*10
if midValue == 0:
num = (highValue -1 +1)*pow(10,count)
sumNum += num
elif midValue > 1:
num = (highValue+1)*pow(10,count)
else:
num = highValue*pow(10,count) + lowValue
sumNum += num
count += 1
return sumNum
a = Solution()
m1 = a.NumberOf1Between1AndN_Solution(13)
print('m1=', m1)
姚老师的代码在n=1的时候不能通过,所以我就加了第一句判断。