Skip to content

Commit

Permalink
Updating approaches for Change after feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
jagdish-15 committed Nov 18, 2024
1 parent 2df72c4 commit 2758bc3
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,11 @@ class ChangeCalculator {
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.
It minimizes the number of coins needed by breaking down the problem into smaller subproblems and solving them progressively.

This approach ensures that we find the most efficient way to make change and handles edge cases where no solution exists.

## Explanation

1. **Initialize Coins Usage Tracker**:

- If the `grandTotal` is negative, an exception is thrown immediately.

Check failure on line 49 in exercises/practice/change/.approaches/dynamic-programming/content.md

View workflow job for this annotation

GitHub Actions / Lint Markdown files

Trailing spaces

exercises/practice/change/.approaches/dynamic-programming/content.md:49:74 MD009/no-trailing-spaces Trailing spaces [Expected: 0 or 2; Actual: 1] https://github.com/DavidAnson/markdownlint/blob/v0.35.0/doc/md009.md
- We create a list `coinsUsed`, where each index `i` stores the most efficient combination of coins that sum up to the value `i`.
- The list is initialized with an empty list at index `0`, as no coins are needed to achieve a total of zero.

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

## Key Points

Check failure on line 64 in exercises/practice/change/.approaches/dynamic-programming/content.md

View workflow job for this annotation

GitHub Actions / Lint Markdown files

Multiple consecutive blank lines

exercises/practice/change/.approaches/dynamic-programming/content.md:64 MD012/no-multiple-blanks Multiple consecutive blank lines [Expected: 1; Actual: 2] https://github.com/DavidAnson/markdownlint/blob/v0.35.0/doc/md012.md
- **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`.

- **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`.

- **Edge Cases**:

- If the `grandTotal` is negative, an exception is thrown immediately.
- If there is no way to make the exact total with the given denominations, an exception is thrown with a descriptive message.

## Conclusion

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`.
However, it’s essential to consider the trade-offs in terms of memory usage and the time complexity when dealing with very large inputs.
48 changes: 38 additions & 10 deletions exercises/practice/change/.approaches/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,44 @@ The solution needs to figure out which totals can be achieved and how to combine

## Approach: Dynamic Programming

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`).
For each total, we track the fewest coins needed to make that total, reusing previous results to make the solution efficient.

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.

## Key Features of the Approach

- **Efficiency**: By building solutions for each increment up to `grandTotal`, this approach minimizes redundant calculations.
- **Flexibility**: Handles cases where exact change is impossible by checking at each step.
- **Scalability**: Works for various coin denominations and totals, though large inputs may impact performance.
```java
import java.util.List;
import java.util.ArrayList;

class ChangeCalculator {
private final List<Integer> currencyCoins;

ChangeCalculator(List<Integer> currencyCoins) {
this.currencyCoins = currencyCoins;
}

List<Integer> computeMostEfficientChange(int grandTotal) {
if (grandTotal < 0)
throw new IllegalArgumentException("Negative totals are not allowed.");

List<List<Integer>> coinsUsed = new ArrayList<>(grandTotal + 1);
coinsUsed.add(new ArrayList<Integer>());

for (int i = 1; i <= grandTotal; i++) {
List<Integer> bestCombination = null;
for (int coin: currencyCoins) {
if (coin <= i && coinsUsed.get(i - coin) != null) {
List<Integer> currentCombination = new ArrayList<>(coinsUsed.get(i - coin));
currentCombination.add(0, coin);
if (bestCombination == null || currentCombination.size() < bestCombination.size())
bestCombination = currentCombination;
}
}
coinsUsed.add(bestCombination);
}

if (coinsUsed.get(grandTotal) == null)
throw new IllegalArgumentException("The total " + grandTotal + " cannot be represented in the given currency.");

return coinsUsed.get(grandTotal);
}
}
```

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

Expand Down

0 comments on commit 2758bc3

Please sign in to comment.