Problem

Write a function that takes a natural number as input and returns the number of digits the input has.

Constraint: don’t use any loops.

Examples

Example 1

1
2
3
Input: 123
Output: 3
Explanation: The number 123 has 3 digits: 1, 2, and 3.

Example 2

1
2
3
Input: 1
Output: 1
Explanation: Single digit number has 1 digit.

Example 3

1
2
3
Input: 1000
Output: 4
Explanation: The number 1000 has 4 digits: 1, 0, 0, and 0.

Example 4

1
2
3
Input: 999999
Output: 6
Explanation: The number 999999 has 6 digits.

Example 5

1
2
3
Input: 0
Output: 1
Explanation: Zero is considered to have 1 digit.

Solution

Method 1 - Logarithmic Calculation

Intuition

The key insight is that the number of digits in a positive integer n is floor(log₁₀(n)) + 1. This works because log₁₀(n) tells us the power of 10, and adding 1 gives us the digit count. For example, log₁₀(123) ≈ 2.09, so floor(2.09) + 1 = 3 digits. We need to handle the special case of 0 separately since log₁₀(0) is undefined.

Approach

  1. Handle Edge Case: Check if the number is 0, return 1 (since 0 has 1 digit)
  2. Handle Negative Numbers: Take absolute value if dealing with negative numbers
  3. Apply Logarithm: Calculate log₁₀(n) using natural logarithm: log₁₀(n) = ln(n) / ln(10)
  4. Floor and Add One: Take floor of the result and add 1 to get digit count
  5. Return Result: The calculated digit count

Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public:
    int countDigits(int n) {
        if (n == 0) return 1;
        
        // Handle negative numbers by taking absolute value
        n = abs(n);
        
        // Use logarithm: digits = floor(log10(n)) + 1
        return static_cast<int>(floor(log10(n))) + 1;
    }
    
    // Alternative using natural logarithm
    int countDigitsAlt(int n) {
        if (n == 0) return 1;
        
        n = abs(n);
        
        // log10(n) = ln(n) / ln(10)
        return static_cast<int>(floor(log(n) / log(10))) + 1;
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
func CountDigits(n int) int {
    if n == 0 {
        return 1
    }
    
    // Handle negative numbers
    if n < 0 {
        n = -n
    }
    
    // Use logarithm: digits = floor(log10(n)) + 1
    return int(math.Floor(math.Log10(float64(n)))) + 1
}

func CountDigitsAlt(n int) int {
    if n == 0 {
        return 1
    }
    
    if n < 0 {
        n = -n
    }
    
    // log10(n) = ln(n) / ln(10)
    return int(math.Floor(math.Log(float64(n))/math.Log(10))) + 1
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Solution {
    public int countDigits(int n) {
        if (n == 0) return 1;
        
        // Handle negative numbers
        n = Math.abs(n);
        
        // Use logarithm: digits = floor(log10(n)) + 1
        return (int) Math.floor(Math.log10(n)) + 1;
    }
    
    public int countDigitsAlt(int n) {
        if (n == 0) return 1;
        
        n = Math.abs(n);
        
        // log10(n) = ln(n) / ln(10)
        return (int) Math.floor(Math.log(n) / Math.log(10)) + 1;
    }
    
    // Version for long numbers
    public int countDigitsLong(long n) {
        if (n == 0) return 1;
        
        n = Math.abs(n);
        
        return (int) Math.floor(Math.log10(n)) + 1;
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution:
    def countDigits(self, n: int) -> int:
        if n == 0:
            return 1
        
        # Handle negative numbers
        n = abs(n)
        
        # Use logarithm: digits = floor(log10(n)) + 1
        import math
        return int(math.floor(math.log10(n))) + 1
    
    def countDigitsAlt(self, n: int) -> int:
        if n == 0:
            return 1
        
        n = abs(n)
        
        # log10(n) = ln(n) / ln(10)
        import math
        return int(math.floor(math.log(n) / math.log(10))) + 1

Complexity

  • ⏰ Time complexity: O(1) as logarithm calculation is a constant time operation.
  • 🧺 Space complexity: O(1) as we only use a constant amount of extra space.

Method 2 - Recursive Division

Intuition

We can count digits recursively by dividing the number by 10 until it becomes 0. Each division represents removing one digit, so we count how many divisions we can perform. The base case is when the number becomes 0, and the recursive case is counting 1 plus the digits of n/10. This avoids loops while still achieving the counting goal.

Approach

  1. Base Case: If n is 0, return 1 (for the case when input is 0) or 0 (for recursive calls)
  2. Handle Negative: Take absolute value to handle negative numbers
  3. Recursive Call: Return 1 + countDigits(n/10) for the recursive division
  4. Division Process: Each call reduces the number by one digit
  5. Count Accumulation: Each recursive call adds 1 to the total count

Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Solution {
public:
    int countDigitsRecursive(int n) {
        // Handle the edge case of 0
        if (n == 0) return 1;
        
        // Handle negative numbers
        n = abs(n);
        
        return countHelper(n);
    }
    
private:
    int countHelper(int n) {
        // Base case: no more digits
        if (n == 0) return 0;
        
        // Recursive case: 1 digit + digits in n/10
        return 1 + countHelper(n / 10);
    }
    
public:
    // Alternative single function approach
    int countDigitsRecursiveAlt(int n) {
        if (n == 0) return 1;  // Special case for input 0
        
        n = abs(n);  // Handle negative numbers
        
        if (n < 10) return 1;  // Single digit
        
        return 1 + countDigitsRecursiveAlt(n / 10);
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
func CountDigitsRecursive(n int) int {
    // Handle edge case of 0
    if n == 0 {
        return 1
    }
    
    // Handle negative numbers
    if n < 0 {
        n = -n
    }
    
    return countHelper(n)
}

func countHelper(n int) int {
    // Base case: no more digits
    if n == 0 {
        return 0
    }
    
    // Recursive case: 1 digit + digits in n/10
    return 1 + countHelper(n/10)
}

func CountDigitsRecursiveAlt(n int) int {
    if n == 0 {
        return 1  // Special case for input 0
    }
    
    if n < 0 {
        n = -n  // Handle negative numbers
    }
    
    if n < 10 {
        return 1  // Single digit
    }
    
    return 1 + CountDigitsRecursiveAlt(n/10)
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class Solution {
    public int countDigitsRecursive(int n) {
        // Handle edge case of 0
        if (n == 0) return 1;
        
        // Handle negative numbers
        n = Math.abs(n);
        
        return countHelper(n);
    }
    
    private int countHelper(int n) {
        // Base case: no more digits
        if (n == 0) return 0;
        
        // Recursive case: 1 digit + digits in n/10
        return 1 + countHelper(n / 10);
    }
    
    public int countDigitsRecursiveAlt(int n) {
        if (n == 0) return 1;  // Special case for input 0
        
        n = Math.abs(n);  // Handle negative numbers
        
        if (n < 10) return 1;  // Single digit
        
        return 1 + countDigitsRecursiveAlt(n / 10);
    }
    
    // Tail recursive version for better performance
    public int countDigitsTailRecursive(int n) {
        if (n == 0) return 1;
        
        n = Math.abs(n);
        
        return countTailHelper(n, 0);
    }
    
    private int countTailHelper(int n, int count) {
        if (n == 0) return count;
        
        return countTailHelper(n / 10, count + 1);
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class Solution:
    def countDigitsRecursive(self, n: int) -> int:
        # Handle edge case of 0
        if n == 0:
            return 1
        
        # Handle negative numbers
        n = abs(n)
        
        return self._countHelper(n)
    
    def _countHelper(self, n: int) -> int:
        # Base case: no more digits
        if n == 0:
            return 0
        
        # Recursive case: 1 digit + digits in n//10
        return 1 + self._countHelper(n // 10)
    
    def countDigitsRecursiveAlt(self, n: int) -> int:
        if n == 0:
            return 1  # Special case for input 0
        
        n = abs(n)  # Handle negative numbers
        
        if n < 10:
            return 1  # Single digit
        
        return 1 + self.countDigitsRecursiveAlt(n // 10)
    
    def countDigitsTailRecursive(self, n: int) -> int:
        if n == 0:
            return 1
        
        n = abs(n)
        
        return self._countTailHelper(n, 0)
    
    def _countTailHelper(self, n: int, count: int) -> int:
        if n == 0:
            return count
        
        return self._countTailHelper(n // 10, count + 1)

Complexity

  • ⏰ Time complexity: O(log₁₀(n)) where n is the input number, as we make one recursive call for each digit.
  • 🧺 Space complexity: O(log₁₀(n)) due to the recursive call stack depth, which is proportional to the number of digits.

Method 3 - String Conversion

Intuition

The simplest approach is to convert the number to a string and count its length. This leverages the built-in string conversion which handles all edge cases automatically. For negative numbers, we need to subtract 1 from the length to exclude the minus sign. This method is straightforward and handles all cases naturally without complex logic.

Approach

  1. Convert to String: Use built-in function to convert number to string representation
  2. Handle Negative: Check if the number is negative and adjust accordingly
  3. Count Characters: Get the length of the string
  4. Adjust for Sign: Subtract 1 if the number was negative (to exclude minus sign)
  5. Return Length: The string length represents the digit count

Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public:
    int countDigitsString(int n) {
        string str = to_string(n);
        
        // If negative, subtract 1 for the minus sign
        return str.length() - (n < 0 ? 1 : 0);
    }
    
    // Version using absolute value
    int countDigitsStringAbs(int n) {
        return to_string(abs(n)).length();
    }
    
    // Template version for different numeric types
    template<typename T>
    int countDigitsTemplate(T n) {
        return to_string(abs(n)).length();
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
func CountDigitsString(n int) int {
    str := strconv.Itoa(n)
    
    // If negative, subtract 1 for the minus sign
    if n < 0 {
        return len(str) - 1
    }
    
    return len(str)
}

func CountDigitsStringAbs(n int) int {
    if n < 0 {
        n = -n
    }
    
    return len(strconv.Itoa(n))
}

func CountDigitsStringFmt(n int) int {
    str := fmt.Sprintf("%d", n)
    
    if n < 0 {
        return len(str) - 1
    }
    
    return len(str)
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
    public int countDigitsString(int n) {
        String str = String.valueOf(n);
        
        // If negative, subtract 1 for the minus sign
        return str.length() - (n < 0 ? 1 : 0);
    }
    
    public int countDigitsStringAbs(int n) {
        return String.valueOf(Math.abs(n)).length();
    }
    
    // Version using StringBuilder for efficiency
    public int countDigitsStringBuilder(int n) {
        return new StringBuilder().append(Math.abs(n)).length();
    }
    
    // Generic version for different numeric types
    public <T extends Number> int countDigitsGeneric(T n) {
        return String.valueOf(Math.abs(n.doubleValue())).replace(".", "").length();
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class Solution:
    def countDigitsString(self, n: int) -> int:
        str_n = str(n)
        
        # If negative, subtract 1 for the minus sign
        return len(str_n) - (1 if n < 0 else 0)
    
    def countDigitsStringAbs(self, n: int) -> int:
        return len(str(abs(n)))
    
    def countDigitsStringFormat(self, n: int) -> int:
        # Using f-string formatting
        return len(f"{abs(n)}")
    
    def countDigitsStringOneliner(self, n: int) -> int:
        return len(str(abs(n)))

Complexity

  • ⏰ Time complexity: O(log₁₀(n)) for the string conversion operation, which needs to process each digit.
  • 🧺 Space complexity: O(log₁₀(n)) for storing the string representation of the number.