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.
Brute force solution o(n) in time, TLE.
// brute force
class Solution {
public:
int countDigitOne(int n) {
int count = 0;
for(int i = 1; i <= n; i++){
int j = i;
while(j > 0){
if(j % 10 == 1){
count++;
break;
}else{
j = j / 10;
}
}
}
return count;
}
};
A better solution.
Count the occurrence of 1 on every bit. Be aware of overflow.
class Solution {
public:
int countDigitOne(int n) {
long pivot = 1;
int count = 0;
while(pivot <= (long)n * 10){
int left = n / (pivot * 10); // left part to pivot
int right = n % pivot; // right part to pivot
int digit = n / pivot % 10; // pivot digit
if(digit == 0) count += left * pivot;
else if(digit == 1) count += left * pivot + right + 1;
else count += left * pivot + pivot;
pivot = pivot * 10;
}
return count;
}
};
Reference: https://leetcode.com/discuss/64962/java-python-one-pass-solution-easy-to-understand
The idea is to calculate occurrence of 1 on every digit. There are 3 scenarios, for example
if n = xyzdabc
and we are considering the occurrence of one on thousand, it should be:
(1) xyz * 1000 if d == 0
(2) xyz * 1000 + abc + 1 if d == 1
(3) xyz * 1000 + 1000 if d > 1
iterate through all digits and sum them all will give the final answer
Java
public int countDigitOne(int n) {
if (n <= 0) return 0;
int q = n, x = 1, ans = 0;
do {
int digit = q % 10;
q /= 10;
ans += q * x;
if (digit == 1) ans += n % x + 1;
if (digit > 1) ans += x;
x *= 10;
} while (q > 0);
return ans;
}
// 40 / 40 test cases passed.
// Status: Accepted
// Runtime: 0 ms
Python
def countDigitOne(self, n):
if n <= 0:
return 0
q, x, ans = n, 1, 0
while q > 0:
digit = q % 10
q /= 10
ans += q * x
if digit == 1:
ans += n % x + 1
elif digit > 1:
ans += x
x *= 10
return ans
# 40 / 40 test cases passed.
# Status: Accepted
# Runtime: 32 ms
# 97.59%