-
-
Notifications
You must be signed in to change notification settings - Fork 738
Adding approach change #2859
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding approach change #2859
Changes from 11 commits
e3cbf38
4a7811f
e8d2787
6152c10
5d398d0
115a331
d2c2451
b3a98df
e338ff2
9438325
fde837b
7ec2960
404de05
1aa6d9c
2fbec2a
c1d07e5
afee45a
d9694fa
7aa412e
f3eb007
0b5b6f2
2df72c4
2758bc3
c0a46c6
f76ad5d
5db8204
505a92d
39f0e69
2dea910
4e0e5e0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| { | ||
| "introduction": { | ||
| "authors": [ | ||
| "jagdish-15" | ||
| ] | ||
| }, | ||
| "approaches": [ | ||
| { | ||
| "uuid": "d0b615ca-3a02-4d66-ad10-e0c513062189", | ||
| "slug": "dynamic-programming", | ||
| "title": "Dynamic Programming Approach", | ||
| "blurb": "Use dynamic programming to find the most efficient change combination.", | ||
| "authors": [ | ||
| "jagdish-15" | ||
| ], | ||
| "contributors": [ | ||
| "kahgoh" | ||
| ] | ||
| } | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,79 @@ | ||||||
| # Dynamic Programming Approach | ||||||
|
|
||||||
| ```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); | ||||||
| } | ||||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| 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 | ||||||
kahgoh marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
|
||||||
| 1. **Initialize Coins Usage Tracker**: | ||||||
|
||||||
| 1. **Initialize Coins Usage Tracker**: | |
| ### Initialize Coins Usage Tracker |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would make sense much more as a sub-heading!
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 2. **Iterative Dynamic Programming**: | |
| ### Iterative Dynamic Programming |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 3. **Result**: | |
| ### Result |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the core of this document should be focusing on the specifics of how the approach works. From that point of view, I think the Key Points heading/section is confusing as Time Complexity and Space Complexity isn't a core part of the implementation, but I do think we can certainly mention them. Perhaps we could remove the heading.
| ## Key Points |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I've removed this heading.
jagdish-15 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
jagdish-15 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest moving the points from the edge cases to be with your explanation as they are part of the implementation details. Idalso suggest separating them to follow the order of the code to make it easier to follow (i.e putting the point about checking if grandTotal is negative to the top and one about if no exact total to the bottom of the explanation).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've moved the first point to the start of the explanation as you suggested and removed the second point since it's already covered at the end, just before the 'Time Complexity' section.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we could remove this conclusion section. Similar to my earlier comment, I think the first sentence is redundant as all approaches have find the optimal solution to be valid. The second sentence would probably make more sense in a Which approach to use? section if we have more approaches.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree! I've removed the conclusion section altogether.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| class ChangeCalculator { | ||
| private final List<Integer> currencyCoins; | ||
|
|
||
| ChangeCalculator(List<Integer> currencyCoins) { | ||
| this.currencyCoins = currencyCoins; | ||
| } | ||
| // computeMostEfficientChange method | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| # Introduction | ||
|
|
||
| There is an idiomatic approach to solving "Change." | ||
| You can use [dynamic programming][dynamic-programming] to calculate the minimum number of coins required for a given total. | ||
|
|
||
| ## General guidance | ||
|
|
||
| The key to solving "Change" is understanding that not all totals can be reached with the available coin denominations. | ||
| The solution needs to figure out which totals can be achieved and how to combine the coins optimally. | ||
|
|
||
| ## Approach: Dynamic Programming | ||
|
|
||
jagdish-15 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 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. | ||
|
|
||
| For a detailed look at the code and logic, see the full explanation in the [Dynamic Programming Approach][approach-dynamic-programming]. | ||
|
|
||
| [approach-dynamic-programming]: https://exercism.org/tracks/java/exercises/change/approaches/dynamic-programming | ||
| [dynamic-programming]: https://en.wikipedia.org/wiki/Dynamic_programming | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find this sentence redundant because all the approaches will need to do this to successfully solve the exercise.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, I can't deny! I will remove this sentence altogether.