Skip to content

Commit 2758bc3

Browse files
committed
Updating approaches for Change after feedback
1 parent 2df72c4 commit 2758bc3

File tree

2 files changed

+39
-23
lines changed

2 files changed

+39
-23
lines changed

exercises/practice/change/.approaches/dynamic-programming/content.md

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,11 @@ class ChangeCalculator {
4242
The **Dynamic Programming (DP)** approach is an efficient way to solve the problem of making change for a given total using a list of available coin denominations.
4343
It minimizes the number of coins needed by breaking down the problem into smaller subproblems and solving them progressively.
4444

45-
This approach ensures that we find the most efficient way to make change and handles edge cases where no solution exists.
46-
4745
## Explanation
4846

4947
1. **Initialize Coins Usage Tracker**:
5048

49+
- If the `grandTotal` is negative, an exception is thrown immediately.
5150
- We create a list `coinsUsed`, where each index `i` stores the most efficient combination of coins that sum up to the value `i`.
5251
- The list is initialized with an empty list at index `0`, as no coins are needed to achieve a total of zero.
5352

@@ -62,18 +61,7 @@ This approach ensures that we find the most efficient way to make change and han
6261
- After processing all values up to `grandTotal`, the combination at `coinsUsed[grandTotal]` will represent the most efficient solution.
6362
- If no valid combination exists for `grandTotal`, an exception is thrown.
6463

65-
## Key Points
6664

6765
- **Time Complexity**: The time complexity of this approach is **O(n * m)**, where `n` is the `grandTotal` and `m` is the number of available coin denominations. This is because we iterate over all coin denominations for each amount up to `grandTotal`.
6866

6967
- **Space Complexity**: The space complexity is **O(n)** due to the list `coinsUsed`, which stores the most efficient coin combination for each total up to `grandTotal`.
70-
71-
- **Edge Cases**:
72-
73-
- If the `grandTotal` is negative, an exception is thrown immediately.
74-
- If there is no way to make the exact total with the given denominations, an exception is thrown with a descriptive message.
75-
76-
## Conclusion
77-
78-
The dynamic programming approach provides an optimal solution for the change-making problem, ensuring that we minimize the number of coins used while efficiently solving the problem for any `grandTotal`.
79-
However, it’s essential to consider the trade-offs in terms of memory usage and the time complexity when dealing with very large inputs.

exercises/practice/change/.approaches/introduction.md

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,44 @@ The solution needs to figure out which totals can be achieved and how to combine
1010

1111
## Approach: Dynamic Programming
1212

13-
Our solution uses a **dynamic programming approach**, where we systematically build up the optimal combinations for all totals from `0` up to the target amount (`grandTotal`).
14-
For each total, we track the fewest coins needed to make that total, reusing previous results to make the solution efficient.
15-
16-
This approach ensures that we find the minimum number of coins required in a structured, repeatable way, avoiding the need for complex recursive calls or excessive backtracking.
17-
18-
## Key Features of the Approach
19-
20-
- **Efficiency**: By building solutions for each increment up to `grandTotal`, this approach minimizes redundant calculations.
21-
- **Flexibility**: Handles cases where exact change is impossible by checking at each step.
22-
- **Scalability**: Works for various coin denominations and totals, though large inputs may impact performance.
13+
```java
14+
import java.util.List;
15+
import java.util.ArrayList;
16+
17+
class ChangeCalculator {
18+
private final List<Integer> currencyCoins;
19+
20+
ChangeCalculator(List<Integer> currencyCoins) {
21+
this.currencyCoins = currencyCoins;
22+
}
23+
24+
List<Integer> computeMostEfficientChange(int grandTotal) {
25+
if (grandTotal < 0)
26+
throw new IllegalArgumentException("Negative totals are not allowed.");
27+
28+
List<List<Integer>> coinsUsed = new ArrayList<>(grandTotal + 1);
29+
coinsUsed.add(new ArrayList<Integer>());
30+
31+
for (int i = 1; i <= grandTotal; i++) {
32+
List<Integer> bestCombination = null;
33+
for (int coin: currencyCoins) {
34+
if (coin <= i && coinsUsed.get(i - coin) != null) {
35+
List<Integer> currentCombination = new ArrayList<>(coinsUsed.get(i - coin));
36+
currentCombination.add(0, coin);
37+
if (bestCombination == null || currentCombination.size() < bestCombination.size())
38+
bestCombination = currentCombination;
39+
}
40+
}
41+
coinsUsed.add(bestCombination);
42+
}
43+
44+
if (coinsUsed.get(grandTotal) == null)
45+
throw new IllegalArgumentException("The total " + grandTotal + " cannot be represented in the given currency.");
46+
47+
return coinsUsed.get(grandTotal);
48+
}
49+
}
50+
```
2351

2452
For a detailed look at the code and logic, see the full explanation in the [Dynamic Programming Approach][approach-dynamic-programming].
2553

0 commit comments

Comments
 (0)