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.
用概率统计来计算,假设从个位开始,每次假设一个进位是1,然后统计剩下位数的数字变化的可能性。
class Solution(object):
def countDigitOne(self, n):
multipler = 1 # 记录位数的移动
count = 0 # 记录1的数量
while multipler <= n:
quotient = n / (multipler * 10) # 得到某一个位数置1后的商
remainder = n % multipler # 得到某一位数置1后的余数
current = (n / multipler) % 10 # 置1位置的当前数值
if current == 0:
count += quotient * multipler
if current == 1: # 这步下面有更新
if not quotient:
count += remainder + 1
else:
count += (quotient * multipler + remainder) + 1
if current > 1:
count += (quotient + 1) * multipler
multipler *= 10
return count
用数字来举例:
@1. 392 -> 180
39x,把个位作为1,那么就有(00~39)种可能性,计40.
3x2,把十位作为1,这里不是(00~32),因为十位大于1,所以个位0~9都可以,依旧是(00~39)中可能性,计40.
x92,把百位作为1,同样因为百位大于1,所以就有(00~99)种可能性,计100.
一共40 + 40 + 100 -> 180
====
大于1的时候
if current > 1:
count += (quotient + 1) * multipler
====
@2. 如果最后一位刚好是1的话
1392 -> 873
同上,139x,有(000~139),计140.
13x2,有(000~139),计140.
1x92,有(000~199),计200.
x392,千位是1,所以不是(000~999),而是只有(000~392)种可能性,计393.
一共140 + 140 + 200 + 393 -> 873
====
首位是1的时候
if not quotient:
count += remainder + 1
只是加上剩余的数
====
@3. 如果之前的位刚好是1的话
111 -> 36
11x,有(00~11),计12. (理由同@1)
1x1,有(00~11),计12. (因为十位是1,所以只有(00~11),之后的(12~19)并不在内,否则就超过了数字最大值。)
x11,有(00~11),计12. (理由同@2)
一共12 + 12 + 12 -> 36
====
如果,非首位是1的话
else:
count += (quotient * multipler + remainder) + 1
因为不能超过数字的最大值,所以非置1位之外的数字的所有可能性。可以和@1,@4比较下
====
if current == 1:
count += (quotient * multipler + remainder) + 1
当前位置是1的时候,可以缩成一句,因为首位是1的话,quotient是0,刚好是remainder+1
@4. 如果之前的位刚好是0的话
102 -> 24
10x,有(00~10),计11. (理由同@1)
1x2,因为刚好是0,所以有(00~09),计10. (因为刚好十位是0,所以(10~19)不可以,生成的数字会超过最大值)
x02,有(00~02),计3. (理由同@2)
一共 11 + 10 + 3 -> 24====
刚好是0的话
if current == 0:
count += quotient * multipler
同样的边界条件,不超过数字的最大值,所以只能是上一位的整数值。
====
=======================
class Solution(object):
def countDigitOne(self, n):
ones, m = 0, 1
while m <= n:
ones += (n/m + 8) / 10 * m + (n/m % 10 == 1) * (n%m + 1)
m *= 10
return ones
很明显的关键在这句
(n/m + 8) / 10 * m + (n/m % 10 == 1) * (n%m + 1)
简单来说,就是第一个方法的缩写。依旧是根据当前位置的数字做判断,有三种需要判断,0,1,>=2.
当0的时候,n/m得到的值,最后一个肯定是0,加上了8,就是abc8这样的数字。然后n/m%10就是0,刚好除尽。所以当时0的时候,就单纯的等于
quotient * multipler
商 * 位
当1的时候,n/m得到的值,最后一个肯定是1,加上了9,就是abc9这样的数字,依旧不变。然后n/m%10就是1,刚好是1。所以当时0的时候,就单纯的等于
quotient * multipler + remainder + 1
商 * 位 + 余数 + 1. (其实不用判断首位是不是1得可能性,因为首位是1的时候,会得到(1+8)/10*m,9/10 是0)。
当大于1的时候,(n/m+8)/10肯定进位,n/m%10肯定不等于1。所以就等于
(quotient + 1) * multipler
(商+1)* 位