Start learning free

LESSON 343 OF 410 · DYNAMIC PROGRAMMING

Numbers with Digit Product P in Python (Time Complexity Analysis Included)

Practice O(n * p * digits) Read the full explanation

Given two non-negative integers n and p, return the number of base-10 numbers with n digits and with the digit product equal to p

Example:

Input: n = 3, p = 6
Output: 9
Explanation: [
    123,
    132,
    213,
    231,
    312,
    321,
    116,
    161,
    611
]
Notes:
n <= 12
STEP 1 OF 10
    Ctrl + Enter to check

    PYTHON · DYNAMIC PROGRAMMING

    Digit Product Numbers in Python, explained

    Understanding the Problem

    The core challenge of this problem is to find all N-digit numbers whose digits multiply to give the product P. This problem is significant in combinatorial number theory and has applications in cryptography and digital signal processing. A common pitfall is to overlook the constraints on the number of digits and the product, leading to inefficient solutions.

    Approach

    To solve this problem, we need to generate all possible N-digit numbers and check if their digits' product equals P. A naive approach would involve generating all N-digit numbers and checking each one, but this is computationally expensive. Instead, we can use a recursive approach to build numbers digit by digit, ensuring the product constraint is met.

    Naive Solution

    The naive solution involves generating all N-digit numbers and checking the product of their digits. This approach is not optimal due to its high time complexity, especially for larger values of N.

    Optimized Solution

    An optimized solution involves using recursion to build numbers digit by digit. We start with an empty number and add digits one by one, ensuring the product of the digits so far does not exceed P. This reduces the number of numbers we need to check significantly.

    Algorithm

    Here is a step-by-step breakdown of the optimized algorithm:

    1. Define a recursive function that takes the current number, the remaining number of digits, and the current product.
    2. If the remaining number of digits is 0, check if the current product equals P. If it does, increment the count.
    3. Otherwise, for each digit from 1 to 9, add the digit to the current number and call the recursive function with the updated number, remaining digits, and product.
    4. Return the count of valid numbers.

    Code Implementation

    def count_numbers_with_product(N, P):
        def helper(current_number, remaining_digits, current_product):
            # Base case: if no more digits are remaining
            if remaining_digits == 0:
                # Check if the current product equals P
                return 1 if current_product == P else 0
            
            count = 0
            # Try adding each digit from 1 to 9
            for digit in range(1, 10):
                # Calculate the new product
                new_product = current_product * digit
                # If the new product exceeds P, skip this digit
                if new_product > P:
                    continue
                # Recur with the new number, one less digit, and the new product
                count += helper(current_number * 10 + digit, remaining_digits - 1, new_product)
            
            return count
        
        # Start the recursion with an empty number, N digits, and a product of 1
        return helper(0, N, 1)
    
    # Example usage
    N = 3
    P = 6
    print(count_numbers_with_product(N, P))  # Output: 9
    

    Complexity Analysis

    The time complexity of the optimized solution is O(9^N), as we try each digit from 1 to 9 for each of the N positions. The space complexity is O(N) due to the recursion stack.

    Edge Cases

    Potential edge cases include:

    • N = 1 and P = 0: No valid numbers as digits are from 1 to 9.
    • P = 0: No valid numbers as the product of digits cannot be zero.
    • N = 12 and P = a large number: Ensure the algorithm handles large inputs efficiently.

    Testing

    To test the solution comprehensively, include a variety of test cases:

    • Simple cases: N = 1, P = 1
    • Edge cases: N = 1, P = 0
    • Complex cases: N = 12, P = 1000

    Use testing frameworks like unittest or pytest for automated testing.

    Thinking and Problem-Solving Tips

    When approaching such problems, break down the problem into smaller parts and think about how to build the solution incrementally. Practice similar problems to improve problem-solving skills and understand different algorithms and their applications.

    Conclusion

    Understanding and solving combinatorial problems like this one is crucial for developing strong problem-solving skills. Practice regularly and explore different approaches to enhance your understanding and efficiency.

    Additional Resources

    For further reading and practice, consider the following resources:

    Keep going with PythonAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free