Number of Digit One
Question
https://leetcode.com/problems/number-of-digit-one/?tab=Description
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.
Tags
- Dynamic Programming
- Maths
Analysis
There are two different solutions: Dynamic Programming and Maths.
Dynamic Programming:
Use a table named ones, ones[x] represents the number of 1 in the range [0, 10^x). We traversal from the highest digit to the lowest digit of the number n.
Claim that the number on the right side of the current digit digit is n, and size is the number of current digits, cnt is the number of 1.
- If
digit > 1, thencnt += digit * ones[size - 1] + 10 ^ (size - 1). - If
digit = 1, thencnt += n + ones[size - 1] + 1
code:
class Solution(object):
def countDigitOne(self, n):
"""
:type n: int
:rtype: int
"""
if n <= 0:
return 0
# initialize ones
ones, x = [0], 0
while 10 ** x <= 0x7FFFFFFF:
ones.append(ones[x] * 10 + 10 ** x)
x += 1
cnt, size = 0, len(str(n))
for digit in str(n):
digit = int(digit)
size -= 1
n -= digit * 10 ** size
if digit > 1:
cnt += digit * ones[size] + 10 ** size
elif digit == 1:
cnt += n + ones[size] + 1
return cnt
Maths: https://discuss.leetcode.com/topic/18054/4-lines-o-log-n-c-java-python
Go through all the digits by using the position multiplier m, where m is 1, 10, 100, ...
Claim the current digit determined by m is curn, then the higher part will be n / m and the lower part will be n % m, curn will be n/m%10. According to the current digit curn is 0, 1, or >=2, there might be three different situations (ones is the number of 1):
- If
curn = 0, thenones = (n/m + 8) / 10 * m - If
curn = 1, thenones = (n/m + 8) / 10 * m + (n % m + 1) - If
curn >= 2, thenones = (n/m + 8) / 10 * m
code:
class Solution(object):
def countDigitOne(self, n):
"""
:type n: int
:rtype: int
"""
ones, m = 0, 1
while m <= n:
ones += (n/m + 8) / 10 * m + (n/m % 10 == 1) * (n%m + 1)
m *= 10
return ones