🧩 Problem Statement
Given a non-negative integer n
, count the total number of digit 1
appearing in all numbers from 1
to n
.
Example 1:
go
Input: n = 13
Output: 6
Explanation: Numbers from 1 to 13 contain six 1's in total: 1, 10, 11, 12, 13.
Example 2:
go
Input: n = 0
Output: 0
🧠 Approach
We need to find an efficient way to count how many times the digit 1
appears in all numbers from 1
to n
. A direct approach that checks each number from 1
to n
would be too slow, especially for larger values of n
. Therefore, we use a more mathematical approach that breaks down the problem using place values.
Steps:
- Digit-by-Digit Analysis:
- We can break down the number
n
digit by digit and calculate how many times the digit 1
appears at each position (units, tens, hundreds, etc.).
- Mathematical Counting:
- For each digit in the number
n
, we can calculate how many numbers up to n
have a 1
in that position.
- Consider the number
n = 2345
. We would calculate how many numbers from 1
to 2345
have a 1
in the units, tens, hundreds, etc.
- Algorithm:
- For each digit position (starting from the rightmost):
- Find how many full sets of numbers exist where the current digit is a
1
in that place.
- Add the count of numbers where the digit at the current place is a
1
.
- Edge Case:
✅ Go Implementation
go
package main
import "fmt"
// Function to count the number of digit '1' in the numbers from 1 to n
func countDigitOne(n int) int {
count := 0
factor := 1
for factor <= n {
lowerNumbers := n - (n / factor) * factor
currentDigit := (n / factor) % 10
higherNumbers := n / (factor * 10)
// Count the number of '1's contributed by the current digit position
if currentDigit == 0 {
count += higherNumbers * factor
} else if currentDigit == 1 {
count += higherNumbers * factor + lowerNumbers + 1
} else {
count += (higherNumbers + 1) * factor
}
// Move to the next digit position
factor *= 10
}
return count
}
// Test the countDigitOne function
func main() {
// Test case 1
fmt.Println(countDigitOne(13)) // Output: 6
// Test case 2
fmt.Println(countDigitOne(0)) // Output: 0
}
📦 Example Usage
go
func main() {
// Test case 1
fmt.Println(countDigitOne(13)) // Output: 6
// Test case 2
fmt.Println(countDigitOne(0)) // Output: 0
// Additional test cases
fmt.Println(countDigitOne(100)) // Output: 21
fmt.Println(countDigitOne(123)) // Output: 57
}
🧠 Explanation of the Code
countDigitOne(n int)
:
- The function counts the number of times the digit
1
appears in all numbers from 1
to n
by analyzing each digit position separately.
factor
is used to process each digit place (units, tens, hundreds, etc.).
- For each digit position, we calculate the number of times
1
appears in that position and add it to the total count
.
Steps in Code:
- We loop through the digits of
n
by increasing factor
from 1
, 10
, 100
, etc.
- For each digit position, we calculate:
lowerNumbers
: The number formed by the digits less significant than the current digit.
currentDigit
: The digit at the current position.
higherNumbers
: The number formed by the digits more significant than the current digit.
- Based on the value of
currentDigit
, we determine how many times 1
appears in that position:
- If
currentDigit == 0
: We only count numbers from the higher part.
- If
currentDigit == 1
: We count numbers from both the higher part and lower part.
- If
currentDigit > 1
: We count all possible numbers in this digit place.
- After processing all digits, we return the total count.
⏱️ Time & Space Complexity
- Time Complexity: O(log n)
- The loop iterates over each digit of the number
n
. Since the number of digits is approximately log(n)
, the time complexity is logarithmic.
- Space Complexity: O(1)
- The space complexity is constant because we are using only a few variables (
count
, factor
, etc.) to store intermediate results.
This solution efficiently counts the number of digit 1
s by breaking down the problem digit by digit. The time complexity is logarithmic, making it feasible for large values of n
.