Problem
You are given:
- coins: An integer array representing coins of different denominations.
- counts: An integer array where
counts[i]represents the maximum number of coins available for the denominationcoins[i]. - amount: An integer representing the total amount of money to form.
You need to compute the number of distinct ways to form amount using the given denominations under the constraints that each denomination has a limited count.
Examples
Example 1
| |
Example 2
| |
Solution
Method 1 - Using Recursion
The naive recursive approach involves trying all possible combinations of coins for each denomination while respecting their availability constraints (limited counts). It explores every possible way to form the amount using the given denominations and their respective counts.
Approach
- Base Case:
- If
amount == 0, return 1 (a valid way is found). - If
amount < 0or there are no denominations left, return 0 (not a valid way).
- If
- Recursive Step:
- For each denomination, try using it from
0tocounts[i]times and recursively solve the subproblem for the reducedamountand updatedcounts.
- For each denomination, try using it from
The naive recursive approach is inefficient due to overlapping subproblems, but it is useful for understanding the problem.
Code
| |
| |
| |
Complexity
- ⏰ Time complexity:
O(counts[0] * counts[1] * ... * counts[n]), wherenis the number of denominations. This is because we try every possible combination of coins. - 🧺 Space complexity:
O(amount), due to the recursion stack.
Method 2 - Using Top-down approach
The naive recursive approach can be optimised using memoization, which avoids recomputing overlapping subproblems. In this approach:
- Use a
memodictionary (or array) to store previously computed results for specificindexandremainingvalues. - This ensures that the function does not recompute the number of ways for the same state multiple times.
Algorithm
- Define a recursive function
helper(index, remaining)that calculates the number of ways to form theremainingamount using coins starting from the givenindex. - Use a dictionary or array
memoto store computed results for(index, remaining)to avoid recomputation. - Modify the recursive approach:
- Before computing the result for the current state
(index, remaining), check whether it already exists inmemo. - If it exists, return the stored result.
- Otherwise, compute the result recursively, store it in
memo, and return it.
- Before computing the result for the current state
Code
| |
| |
| |
Complexity
- ⏰ Time complexity:
O(amount * len(coins) * max(counts))len(coins)is the number of denominations.max(counts)is the maximum number of repetitions we can try for each coin.amountis the dimension of the memoisation table.
- 🧺 Space complexity:
O(amount * len(coins))- Space is used for the memoisation table.
- Maximum depth of recursion stack is
O(len(coins).
Method 3 - Using bottom-up DP (1D array)
Reasoning or Intuition
- This is a variation of the coin change problem with the additional constraint of limited counts for each denomination.
- To solve it, we need to track both the amount we aim to form (
amount) and the number of coins available for each denomination (counts). - A dynamic programming approach can be used:
- Define a DP table
dp[amount+1]wheredp[i]represents the number of ways to form the amounti. - For each coin and its count, update the DP table by considering each valid usage of the coin (from
0tocounts[i]).
- Define a DP table
Approach
- Construct an array
dpwheredp[i]denotes the number of distinct ways to formi. - Initialize
dp[0] = 1since there is one way to form amount0(by using no coins). - For every coin, iterate through the array
dpin the reverse direction (to handle limited counts for each denomination). - For each amount
j, iterate from1tocounts[i](representing the number of times we use the current coin) to calculate contributions. - Return
dp[amount]as the final answer.
Code
| |
| |
| |
Complexity
- ⏰ Time complexity: -
O(amount * sum(counts)), wheresum(counts)is the sum of maximum usages for all denominations. - 🧺 Space complexity: -
O(amount), because thedparray requires space proportional to theamount.