Given an array of digits which is sorted in non-decreasing order. You can write numbers using each digits[i] as many times as we want. For example, if digits = ['1','3','5'], we may write numbers such as '13', '551', and '1351315'.
Return the number of positive integers that can be generated that are less than or equal to a given integer n.
Example 1:
Input: digits = ["1","3","5","7"], n = 100 Output: 20 Explanation: The 20 numbers that can be written are: 1, 3, 5, 7, 11, 13, 15, 17, 31, 33, 35, 37, 51, 53, 55, 57, 71, 73, 75, 77.
Example 2:
Input: digits = ["1","4","9"], n = 1000000000 Output: 29523 Explanation: We can write 3 one digit numbers, 9 two digit numbers, 27 three digit numbers, 81 four digit numbers, 243 five digit numbers, 729 six digit numbers, 2187 seven digit numbers, 6561 eight digit numbers, and 19683 nine digit numbers. In total, this is 29523 integers that can be written using the digits array.
Example 3:
Input: digits = ["7"], n = 8 Output: 1
Constraints:
1 <= digits.length <= 9digits[i].length == 1digits[i] is a digit from '1' to '9'.digits are unique.digits is sorted in non-decreasing order.1 <= n <= 109When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach involves generating every possible number that can be formed using the given digits and then checking if each generated number is less than or equal to the target number. We explore all possible combinations of digits up to the length of the target number. This method guarantees finding all valid numbers, but it might be slow for large target numbers or a larger digit set.
Here's how the algorithm would work step-by-step:
def numbers_at_most_n_given_digit_set_brute_force(digits, number_limit):
number_limit_string = str(number_limit)
number_limit_length = len(number_limit_string)
count_of_valid_numbers = 0
for current_length in range(1, number_limit_length + 1):
count_of_valid_numbers += count_valid_numbers_of_length(
digits, current_length, number_limit_string
)
return count_of_valid_numbers
def count_valid_numbers_of_length(digits, current_length, number_limit_string):
count_of_valid_numbers = 0
# Generate all possible numbers of currentLength using digits.
possible_numbers = generate_all_possible_numbers(digits, current_length)
# Count how many of the generated numbers are valid.
for number in possible_numbers:
if int(number) <= int(number_limit_string):
count_of_valid_numbers += 1
return count_of_valid_numbers
def generate_all_possible_numbers(digits, current_length):
if current_length == 0:
return ['']
if current_length == 1:
return digits
possible_numbers = []
for digit in digits:
# Recursively find all numbers of smaller length
smaller_numbers = generate_all_possible_numbers(digits, current_length - 1)
for smaller_number in smaller_numbers:
possible_numbers.append(digit + smaller_number)
return possible_numbersWe want to count how many numbers we can make using a given set of digits, where those numbers are no bigger than a target number. The key is to compare the digits of our target number with the allowed digits, one position at a time. This lets us avoid checking every single possible number.
Here's how the algorithm would work step-by-step:
def numbers_at_most_n_given_digit_set(digits, number_limit):
number_as_string = str(number_limit)
number_length = len(number_as_string)
count = 0
# Count numbers shorter than the limit
for length in range(1, number_length):
count += len(digits) ** length
for index, digit_from_number in enumerate(number_as_string):
suitable_digits = [digit for digit in digits if digit < digit_from_number]
# Add numbers that are smaller at this position
count += len(suitable_digits) * (len(digits) ** (number_length - index - 1))
# If we find an exact match, continue to the next digit.
if digit_from_number in digits:
if index == number_length - 1:
count += 1
else:
break
return count| Case | How to Handle |
|---|---|
| Empty Digit Set | Return 0 since no numbers can be formed if no digits are allowed |
| N is a single digit number | Count the number of digits in the digit set that are less than or equal to N |
| N is a number with leading zeros | Treat N as its integer representation (remove leading zeros) |
| Digit set contains '0' and N is large | Handle cases where using '0' at the beginning is not allowed when forming numbers less than N. |
| N has repeating digits and digit set contains duplicates | The algorithm must ensure to correctly count all combinations without overcounting from either repeated digits in N or duplicates in the digit set. |
| Very large N leading to potential integer overflow in intermediate calculations | Use appropriate data types (e.g., long) to avoid overflow during calculations involving powers of the digit set size. |
| Digit Set contains digits larger than the leading digit of N | Skip considering digits in the digit set that are already larger than the first digit of N when calculating the count for the first digit position. |
| N consists of only the largest available digit | Ensure the algorithm correctly accounts for the number N itself and all the numbers smaller than it which can be formed from the digit set. |