From 1086a1db314d30a83bf108665db553cff30e3122 Mon Sep 17 00:00:00 2001 From: Yam Borodetsky Date: Wed, 18 Feb 2026 23:18:35 +0500 Subject: [PATCH 1/9] Add Coin Change problem files and update README --- README.md | 3 +++ .../codes/yam/leetcode/coinchange/Solution.java | 7 +++++++ .../yam/leetcode/coinchange/package-info.java | 10 ++++++++++ .../yam/leetcode/coinchange/SolutionTest.java | 14 ++++++++++++++ .../codes/yam/leetcode/coinchange/TestCases.java | 15 +++++++++++++++ 5 files changed, 49 insertions(+) create mode 100644 src/main/java/codes/yam/leetcode/coinchange/Solution.java create mode 100644 src/main/java/codes/yam/leetcode/coinchange/package-info.java create mode 100644 src/test/java/codes/yam/leetcode/coinchange/SolutionTest.java create mode 100644 src/test/java/codes/yam/leetcode/coinchange/TestCases.java diff --git a/README.md b/README.md index 6f8d36a..7b95eb9 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ My LeetCode solutions in Java, focused on clean code and optimal algorithms. | [1][lc-1] | [Two Sum](src/main/java/codes/yam/leetcode/twosum/Solution.java) | Easy | `O(n log n)` | `O(n)` | Yes | | [9][lc-9] | [Palindrome Number](src/main/java/codes/yam/leetcode/palindromenumber/Solution.java) | Easy | `O(log10(n) / 2)` | `O(1)` | No | | [70][lc-70] | [Climbing Stairs](src/main/java/codes/yam/leetcode/climbingstairs/Solution.java) | Easy | `O(n)` | `O(1)` | Yes | +| [322][lc-322] | [Coin Change](src/main/java/codes/yam/leetcode/coinchange/Solution.java) | Medium | TBD | TBD | Yes | | [746][lc-746] | [Min Cost Climbing Stairs](src/main/java/codes/yam/leetcode/mincostclimbingstairs/Solution.java) | Easy | `O(n)` | `O(1)` | No | | [1653][lc-1653] | [Minimum Deletions to Make String Balanced](src/main/java/codes/yam/leetcode/minimumdeletionstomakestringbalanced/Solution.java) | Medium | `O(n)` | `O(1)` | No | @@ -22,6 +23,8 @@ My LeetCode solutions in Java, focused on clean code and optimal algorithms. [lc-70]: https://leetcode.com/problems/climbing-stairs/ +[lc-322]: https://leetcode.com/problems/coin-change/ + [lc-746]: https://leetcode.com/problems/min-cost-climbing-stairs/ [lc-1653]: https://leetcode.com/problems/minimum-deletions-to-make-string-balanced/ diff --git a/src/main/java/codes/yam/leetcode/coinchange/Solution.java b/src/main/java/codes/yam/leetcode/coinchange/Solution.java new file mode 100644 index 0000000..cc1ecb6 --- /dev/null +++ b/src/main/java/codes/yam/leetcode/coinchange/Solution.java @@ -0,0 +1,7 @@ +package codes.yam.leetcode.coinchange; + +class Solution { + int coinChange(int[] coins, int amount) { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/codes/yam/leetcode/coinchange/package-info.java b/src/main/java/codes/yam/leetcode/coinchange/package-info.java new file mode 100644 index 0000000..a018dae --- /dev/null +++ b/src/main/java/codes/yam/leetcode/coinchange/package-info.java @@ -0,0 +1,10 @@ +/** + *

Solutions for the "Coin Change" problem on LeetCode.

+ * + * + * @see Problem Link + */ +package codes.yam.leetcode.coinchange; diff --git a/src/test/java/codes/yam/leetcode/coinchange/SolutionTest.java b/src/test/java/codes/yam/leetcode/coinchange/SolutionTest.java new file mode 100644 index 0000000..bf4f191 --- /dev/null +++ b/src/test/java/codes/yam/leetcode/coinchange/SolutionTest.java @@ -0,0 +1,14 @@ +package codes.yam.leetcode.coinchange; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +class SolutionTest { + @ParameterizedTest + @MethodSource("codes.yam.leetcode.coinchange.TestCases#cases") + void coinChange(int[] coins, int amount, int expected) { + assertEquals(expected, new Solution().coinChange(coins, amount)); + } +} diff --git a/src/test/java/codes/yam/leetcode/coinchange/TestCases.java b/src/test/java/codes/yam/leetcode/coinchange/TestCases.java new file mode 100644 index 0000000..7f8d604 --- /dev/null +++ b/src/test/java/codes/yam/leetcode/coinchange/TestCases.java @@ -0,0 +1,15 @@ +package codes.yam.leetcode.coinchange; + +import java.util.stream.Stream; +import org.junit.jupiter.params.provider.Arguments; + +@SuppressWarnings("unused") +class TestCases { + static Stream cases() { + return Stream.of( + Arguments.of(new int[]{1, 2, 5}, 11, 3), + Arguments.of(new int[]{2}, 3, -1), + Arguments.of(new int[]{1}, 0, 0) + ); + } +} From 9b233316d4227fc95f82a5c9163c8f228cca7441 Mon Sep 17 00:00:00 2001 From: Yam Borodetsky Date: Wed, 18 Feb 2026 23:18:47 +0500 Subject: [PATCH 2/9] Refactor package-info and test cases for coin change problem --- .../java/codes/yam/leetcode/coinchange/package-info.java | 7 ++++--- src/test/java/codes/yam/leetcode/coinchange/TestCases.java | 7 +++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/codes/yam/leetcode/coinchange/package-info.java b/src/main/java/codes/yam/leetcode/coinchange/package-info.java index a018dae..19e8855 100644 --- a/src/main/java/codes/yam/leetcode/coinchange/package-info.java +++ b/src/main/java/codes/yam/leetcode/coinchange/package-info.java @@ -1,8 +1,9 @@ /** - *

Solutions for the "Coin Change" problem on LeetCode.

+ * Solutions for the "Coin Change" problem on LeetCode. + * *
    - *
  • Slug: coin-change
  • - *
  • Difficulty: Medium
  • + *
  • Slug: coin-change + *
  • Difficulty: Medium *
* * @see Problem Link diff --git a/src/test/java/codes/yam/leetcode/coinchange/TestCases.java b/src/test/java/codes/yam/leetcode/coinchange/TestCases.java index 7f8d604..b3b307c 100644 --- a/src/test/java/codes/yam/leetcode/coinchange/TestCases.java +++ b/src/test/java/codes/yam/leetcode/coinchange/TestCases.java @@ -7,9 +7,8 @@ class TestCases { static Stream cases() { return Stream.of( - Arguments.of(new int[]{1, 2, 5}, 11, 3), - Arguments.of(new int[]{2}, 3, -1), - Arguments.of(new int[]{1}, 0, 0) - ); + Arguments.of(new int[] {1, 2, 5}, 11, 3), + Arguments.of(new int[] {2}, 3, -1), + Arguments.of(new int[] {1}, 0, 0)); } } From 9067293ceb5e8c9c3d7aba10580403b90f3819bf Mon Sep 17 00:00:00 2001 From: Yam Borodetsky Date: Thu, 19 Feb 2026 00:15:08 +0500 Subject: [PATCH 3/9] Implement dynamic programming solution for Coin Change problem --- .../yam/leetcode/coinchange/Solution.java | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/main/java/codes/yam/leetcode/coinchange/Solution.java b/src/main/java/codes/yam/leetcode/coinchange/Solution.java index cc1ecb6..6e88d12 100644 --- a/src/main/java/codes/yam/leetcode/coinchange/Solution.java +++ b/src/main/java/codes/yam/leetcode/coinchange/Solution.java @@ -2,6 +2,26 @@ class Solution { int coinChange(int[] coins, int amount) { - throw new UnsupportedOperationException(); + if (amount == 0) return 0; + if (amount < 0) return -1; + int[] dp = new int[amount + 1]; + for (int a = 1; a <= amount; a++) { + boolean useMin = true; + int min = Integer.MAX_VALUE; + for (int c : coins) { + if (c > a) continue; + if (c == a) { + dp[a] = 1; + useMin = false; + continue; + } + if (dp[a - c] == -1) continue; + min = Math.min(min, 1 + dp[a - c]); + } + if (useMin) { + dp[a] = min == Integer.MAX_VALUE ? -1 : min; + } + } + return dp[amount]; } } From e72ac10f8fdeddb711f46e2fd5b58ad0f1e64d87 Mon Sep 17 00:00:00 2001 From: Yam Borodetsky Date: Thu, 19 Feb 2026 00:34:57 +0500 Subject: [PATCH 4/9] Refactor coin change solution to use dynamic programming --- .../{Solution.java => SolutionDp.java} | 2 +- .../leetcode/coinchange/SolutionDpNaive.java | 27 +++++++++++++++++++ .../coinchange/SolutionDpNaiveTest.java | 14 ++++++++++ ...{SolutionTest.java => SolutionDpTest.java} | 4 +-- 4 files changed, 44 insertions(+), 3 deletions(-) rename src/main/java/codes/yam/leetcode/coinchange/{Solution.java => SolutionDp.java} (97%) create mode 100644 src/main/java/codes/yam/leetcode/coinchange/SolutionDpNaive.java create mode 100644 src/test/java/codes/yam/leetcode/coinchange/SolutionDpNaiveTest.java rename src/test/java/codes/yam/leetcode/coinchange/{SolutionTest.java => SolutionDpTest.java} (79%) diff --git a/src/main/java/codes/yam/leetcode/coinchange/Solution.java b/src/main/java/codes/yam/leetcode/coinchange/SolutionDp.java similarity index 97% rename from src/main/java/codes/yam/leetcode/coinchange/Solution.java rename to src/main/java/codes/yam/leetcode/coinchange/SolutionDp.java index 6e88d12..a759242 100644 --- a/src/main/java/codes/yam/leetcode/coinchange/Solution.java +++ b/src/main/java/codes/yam/leetcode/coinchange/SolutionDp.java @@ -1,6 +1,6 @@ package codes.yam.leetcode.coinchange; -class Solution { +class SolutionDp { int coinChange(int[] coins, int amount) { if (amount == 0) return 0; if (amount < 0) return -1; diff --git a/src/main/java/codes/yam/leetcode/coinchange/SolutionDpNaive.java b/src/main/java/codes/yam/leetcode/coinchange/SolutionDpNaive.java new file mode 100644 index 0000000..4517cc3 --- /dev/null +++ b/src/main/java/codes/yam/leetcode/coinchange/SolutionDpNaive.java @@ -0,0 +1,27 @@ +package codes.yam.leetcode.coinchange; + +class SolutionDpNaive { + int coinChange(int[] coins, int amount) { + if (amount == 0) return 0; + if (amount < 0) return -1; + int[] dp = new int[amount + 1]; + for (int a = 1; a <= amount; a++) { + boolean useMin = true; + int min = Integer.MAX_VALUE; + for (int c : coins) { + if (c > a) continue; + if (c == a) { + dp[a] = 1; + useMin = false; + continue; + } + if (dp[a - c] == -1) continue; + min = Math.min(min, 1 + dp[a - c]); + } + if (useMin) { + dp[a] = min == Integer.MAX_VALUE ? -1 : min; + } + } + return dp[amount]; + } +} diff --git a/src/test/java/codes/yam/leetcode/coinchange/SolutionDpNaiveTest.java b/src/test/java/codes/yam/leetcode/coinchange/SolutionDpNaiveTest.java new file mode 100644 index 0000000..1c4901d --- /dev/null +++ b/src/test/java/codes/yam/leetcode/coinchange/SolutionDpNaiveTest.java @@ -0,0 +1,14 @@ +package codes.yam.leetcode.coinchange; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +class SolutionDpNaiveTest { + @ParameterizedTest + @MethodSource("codes.yam.leetcode.coinchange.TestCases#cases") + void coinChange(int[] coins, int amount, int expected) { + assertEquals(expected, new SolutionDpNaive().coinChange(coins, amount)); + } +} diff --git a/src/test/java/codes/yam/leetcode/coinchange/SolutionTest.java b/src/test/java/codes/yam/leetcode/coinchange/SolutionDpTest.java similarity index 79% rename from src/test/java/codes/yam/leetcode/coinchange/SolutionTest.java rename to src/test/java/codes/yam/leetcode/coinchange/SolutionDpTest.java index bf4f191..976a198 100644 --- a/src/test/java/codes/yam/leetcode/coinchange/SolutionTest.java +++ b/src/test/java/codes/yam/leetcode/coinchange/SolutionDpTest.java @@ -5,10 +5,10 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; -class SolutionTest { +class SolutionDpTest { @ParameterizedTest @MethodSource("codes.yam.leetcode.coinchange.TestCases#cases") void coinChange(int[] coins, int amount, int expected) { - assertEquals(expected, new Solution().coinChange(coins, amount)); + assertEquals(expected, new SolutionDp().coinChange(coins, amount)); } } From cefc9c013be75717f4d4c2c8289a219510ea0bd3 Mon Sep 17 00:00:00 2001 From: Yam Borodetsky Date: Thu, 19 Feb 2026 00:35:38 +0500 Subject: [PATCH 5/9] Refactor Coin Change solution to use a better DP sentinel --- README.md | 2 +- .../codes/yam/leetcode/coinchange/package-info.java | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7b95eb9..7af6465 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ My LeetCode solutions in Java, focused on clean code and optimal algorithms. | [1][lc-1] | [Two Sum](src/main/java/codes/yam/leetcode/twosum/Solution.java) | Easy | `O(n log n)` | `O(n)` | Yes | | [9][lc-9] | [Palindrome Number](src/main/java/codes/yam/leetcode/palindromenumber/Solution.java) | Easy | `O(log10(n) / 2)` | `O(1)` | No | | [70][lc-70] | [Climbing Stairs](src/main/java/codes/yam/leetcode/climbingstairs/Solution.java) | Easy | `O(n)` | `O(1)` | Yes | -| [322][lc-322] | [Coin Change](src/main/java/codes/yam/leetcode/coinchange/Solution.java) | Medium | TBD | TBD | Yes | +| [322][lc-322] | [Coin Change](src/main/java/codes/yam/leetcode/coinchange/SolutionDp.java) | Medium | TBD | TBD | Yes | | [746][lc-746] | [Min Cost Climbing Stairs](src/main/java/codes/yam/leetcode/mincostclimbingstairs/Solution.java) | Easy | `O(n)` | `O(1)` | No | | [1653][lc-1653] | [Minimum Deletions to Make String Balanced](src/main/java/codes/yam/leetcode/minimumdeletionstomakestringbalanced/Solution.java) | Medium | `O(n)` | `O(1)` | No | diff --git a/src/main/java/codes/yam/leetcode/coinchange/package-info.java b/src/main/java/codes/yam/leetcode/coinchange/package-info.java index 19e8855..1845998 100644 --- a/src/main/java/codes/yam/leetcode/coinchange/package-info.java +++ b/src/main/java/codes/yam/leetcode/coinchange/package-info.java @@ -6,6 +6,18 @@ *
  • Difficulty: Medium * * + *

    Solution progression: + * + *

      + *
    1. {@link codes.yam.leetcode.coinchange.SolutionDpNaive} — bottom-up DP using {@code -1} as + * the sentinel for unreachable states. Requires special-casing {@code c == amount} and a + * {@code useMin} flag to avoid treating unset cells as valid. + *
    2. {@link codes.yam.leetcode.coinchange.SolutionDp} — same bottom-up DP, but uses {@code + * amount + 1} as the infinity sentinel. Since {@code ∞ + 1 = ∞} and {@code min(∞, x) = x}, + * the sentinel is algebraically compatible with the recurrence and all special cases + * collapse. + *
    + * * @see Problem Link */ package codes.yam.leetcode.coinchange; From 47d0e9690b22337d385b62f7889f76becd796273 Mon Sep 17 00:00:00 2001 From: Yam Borodetsky Date: Thu, 19 Feb 2026 00:40:48 +0500 Subject: [PATCH 6/9] Refactor DP solution for coin change to simplify logic --- .../yam/leetcode/coinchange/SolutionDp.java | 17 +++-------------- .../leetcode/coinchange/SolutionDpNaive.java | 1 - 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/src/main/java/codes/yam/leetcode/coinchange/SolutionDp.java b/src/main/java/codes/yam/leetcode/coinchange/SolutionDp.java index a759242..3a37bc9 100644 --- a/src/main/java/codes/yam/leetcode/coinchange/SolutionDp.java +++ b/src/main/java/codes/yam/leetcode/coinchange/SolutionDp.java @@ -2,26 +2,15 @@ class SolutionDp { int coinChange(int[] coins, int amount) { - if (amount == 0) return 0; - if (amount < 0) return -1; int[] dp = new int[amount + 1]; for (int a = 1; a <= amount; a++) { - boolean useMin = true; - int min = Integer.MAX_VALUE; + int min = amount + 1; for (int c : coins) { if (c > a) continue; - if (c == a) { - dp[a] = 1; - useMin = false; - continue; - } - if (dp[a - c] == -1) continue; min = Math.min(min, 1 + dp[a - c]); } - if (useMin) { - dp[a] = min == Integer.MAX_VALUE ? -1 : min; - } + dp[a] = min; } - return dp[amount]; + return dp[amount] > amount ? -1 : dp[amount]; } } diff --git a/src/main/java/codes/yam/leetcode/coinchange/SolutionDpNaive.java b/src/main/java/codes/yam/leetcode/coinchange/SolutionDpNaive.java index 4517cc3..0a35415 100644 --- a/src/main/java/codes/yam/leetcode/coinchange/SolutionDpNaive.java +++ b/src/main/java/codes/yam/leetcode/coinchange/SolutionDpNaive.java @@ -3,7 +3,6 @@ class SolutionDpNaive { int coinChange(int[] coins, int amount) { if (amount == 0) return 0; - if (amount < 0) return -1; int[] dp = new int[amount + 1]; for (int a = 1; a <= amount; a++) { boolean useMin = true; From 20c61781973108251c45692c6dbf0c609c3daeb9 Mon Sep 17 00:00:00 2001 From: Yam Borodetsky Date: Thu, 19 Feb 2026 00:47:34 +0500 Subject: [PATCH 7/9] Optimize DP initialization and transition for coin change --- .../codes/yam/leetcode/coinchange/SolutionDp.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/codes/yam/leetcode/coinchange/SolutionDp.java b/src/main/java/codes/yam/leetcode/coinchange/SolutionDp.java index 3a37bc9..27c0c6c 100644 --- a/src/main/java/codes/yam/leetcode/coinchange/SolutionDp.java +++ b/src/main/java/codes/yam/leetcode/coinchange/SolutionDp.java @@ -1,16 +1,21 @@ package codes.yam.leetcode.coinchange; +import java.util.Arrays; + class SolutionDp { int coinChange(int[] coins, int amount) { int[] dp = new int[amount + 1]; + Arrays.fill(dp, 1, amount + 1, amount + 1); for (int a = 1; a <= amount; a++) { - int min = amount + 1; for (int c : coins) { - if (c > a) continue; - min = Math.min(min, 1 + dp[a - c]); + if (c <= a) { + dp[a] = Math.min(dp[a], 1 + dp[a - c]); + } } - dp[a] = min; } - return dp[amount] > amount ? -1 : dp[amount]; + if (dp[amount] > amount) { + return -1; + } + return dp[amount]; } } From 753e11c2b923e9cffbe057077cf98af91322996e Mon Sep 17 00:00:00 2001 From: Yam Borodetsky Date: Thu, 19 Feb 2026 00:48:33 +0500 Subject: [PATCH 8/9] Refactor coin change solutions to remove DP suffix from names --- README.md | 2 +- .../coinchange/{SolutionDp.java => Solution.java} | 2 +- .../{SolutionDpNaive.java => SolutionNaive.java} | 2 +- .../codes/yam/leetcode/coinchange/package-info.java | 13 ++++++------- ...utionDpNaiveTest.java => SolutionNaiveTest.java} | 4 ++-- .../{SolutionDpTest.java => SolutionTest.java} | 4 ++-- 6 files changed, 13 insertions(+), 14 deletions(-) rename src/main/java/codes/yam/leetcode/coinchange/{SolutionDp.java => Solution.java} (95%) rename src/main/java/codes/yam/leetcode/coinchange/{SolutionDpNaive.java => SolutionNaive.java} (96%) rename src/test/java/codes/yam/leetcode/coinchange/{SolutionDpNaiveTest.java => SolutionNaiveTest.java} (77%) rename src/test/java/codes/yam/leetcode/coinchange/{SolutionDpTest.java => SolutionTest.java} (79%) diff --git a/README.md b/README.md index 7af6465..7b95eb9 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ My LeetCode solutions in Java, focused on clean code and optimal algorithms. | [1][lc-1] | [Two Sum](src/main/java/codes/yam/leetcode/twosum/Solution.java) | Easy | `O(n log n)` | `O(n)` | Yes | | [9][lc-9] | [Palindrome Number](src/main/java/codes/yam/leetcode/palindromenumber/Solution.java) | Easy | `O(log10(n) / 2)` | `O(1)` | No | | [70][lc-70] | [Climbing Stairs](src/main/java/codes/yam/leetcode/climbingstairs/Solution.java) | Easy | `O(n)` | `O(1)` | Yes | -| [322][lc-322] | [Coin Change](src/main/java/codes/yam/leetcode/coinchange/SolutionDp.java) | Medium | TBD | TBD | Yes | +| [322][lc-322] | [Coin Change](src/main/java/codes/yam/leetcode/coinchange/Solution.java) | Medium | TBD | TBD | Yes | | [746][lc-746] | [Min Cost Climbing Stairs](src/main/java/codes/yam/leetcode/mincostclimbingstairs/Solution.java) | Easy | `O(n)` | `O(1)` | No | | [1653][lc-1653] | [Minimum Deletions to Make String Balanced](src/main/java/codes/yam/leetcode/minimumdeletionstomakestringbalanced/Solution.java) | Medium | `O(n)` | `O(1)` | No | diff --git a/src/main/java/codes/yam/leetcode/coinchange/SolutionDp.java b/src/main/java/codes/yam/leetcode/coinchange/Solution.java similarity index 95% rename from src/main/java/codes/yam/leetcode/coinchange/SolutionDp.java rename to src/main/java/codes/yam/leetcode/coinchange/Solution.java index 27c0c6c..ce18ac9 100644 --- a/src/main/java/codes/yam/leetcode/coinchange/SolutionDp.java +++ b/src/main/java/codes/yam/leetcode/coinchange/Solution.java @@ -2,7 +2,7 @@ import java.util.Arrays; -class SolutionDp { +class Solution { int coinChange(int[] coins, int amount) { int[] dp = new int[amount + 1]; Arrays.fill(dp, 1, amount + 1, amount + 1); diff --git a/src/main/java/codes/yam/leetcode/coinchange/SolutionDpNaive.java b/src/main/java/codes/yam/leetcode/coinchange/SolutionNaive.java similarity index 96% rename from src/main/java/codes/yam/leetcode/coinchange/SolutionDpNaive.java rename to src/main/java/codes/yam/leetcode/coinchange/SolutionNaive.java index 0a35415..d02d3b7 100644 --- a/src/main/java/codes/yam/leetcode/coinchange/SolutionDpNaive.java +++ b/src/main/java/codes/yam/leetcode/coinchange/SolutionNaive.java @@ -1,6 +1,6 @@ package codes.yam.leetcode.coinchange; -class SolutionDpNaive { +class SolutionNaive { int coinChange(int[] coins, int amount) { if (amount == 0) return 0; int[] dp = new int[amount + 1]; diff --git a/src/main/java/codes/yam/leetcode/coinchange/package-info.java b/src/main/java/codes/yam/leetcode/coinchange/package-info.java index 1845998..586ff94 100644 --- a/src/main/java/codes/yam/leetcode/coinchange/package-info.java +++ b/src/main/java/codes/yam/leetcode/coinchange/package-info.java @@ -9,13 +9,12 @@ *

    Solution progression: * *

      - *
    1. {@link codes.yam.leetcode.coinchange.SolutionDpNaive} — bottom-up DP using {@code -1} as - * the sentinel for unreachable states. Requires special-casing {@code c == amount} and a - * {@code useMin} flag to avoid treating unset cells as valid. - *
    2. {@link codes.yam.leetcode.coinchange.SolutionDp} — same bottom-up DP, but uses {@code - * amount + 1} as the infinity sentinel. Since {@code ∞ + 1 = ∞} and {@code min(∞, x) = x}, - * the sentinel is algebraically compatible with the recurrence and all special cases - * collapse. + *
    3. {@link codes.yam.leetcode.coinchange.SolutionNaive} — bottom-up DP using {@code -1} as the + * sentinel for unreachable states. Requires special-casing {@code c == amount} and a {@code + * useMin} flag to avoid treating unset cells as valid. + *
    4. {@link codes.yam.leetcode.coinchange.Solution} — same bottom-up DP, but uses {@code amount + * + 1} as the infinity sentinel. Since {@code ∞ + 1 = ∞} and {@code min(∞, x) = x}, the + * sentinel is algebraically compatible with the recurrence and all special cases collapse. *
    * * @see Problem Link diff --git a/src/test/java/codes/yam/leetcode/coinchange/SolutionDpNaiveTest.java b/src/test/java/codes/yam/leetcode/coinchange/SolutionNaiveTest.java similarity index 77% rename from src/test/java/codes/yam/leetcode/coinchange/SolutionDpNaiveTest.java rename to src/test/java/codes/yam/leetcode/coinchange/SolutionNaiveTest.java index 1c4901d..03b0909 100644 --- a/src/test/java/codes/yam/leetcode/coinchange/SolutionDpNaiveTest.java +++ b/src/test/java/codes/yam/leetcode/coinchange/SolutionNaiveTest.java @@ -5,10 +5,10 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; -class SolutionDpNaiveTest { +class SolutionNaiveTest { @ParameterizedTest @MethodSource("codes.yam.leetcode.coinchange.TestCases#cases") void coinChange(int[] coins, int amount, int expected) { - assertEquals(expected, new SolutionDpNaive().coinChange(coins, amount)); + assertEquals(expected, new SolutionNaive().coinChange(coins, amount)); } } diff --git a/src/test/java/codes/yam/leetcode/coinchange/SolutionDpTest.java b/src/test/java/codes/yam/leetcode/coinchange/SolutionTest.java similarity index 79% rename from src/test/java/codes/yam/leetcode/coinchange/SolutionDpTest.java rename to src/test/java/codes/yam/leetcode/coinchange/SolutionTest.java index 976a198..bf4f191 100644 --- a/src/test/java/codes/yam/leetcode/coinchange/SolutionDpTest.java +++ b/src/test/java/codes/yam/leetcode/coinchange/SolutionTest.java @@ -5,10 +5,10 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; -class SolutionDpTest { +class SolutionTest { @ParameterizedTest @MethodSource("codes.yam.leetcode.coinchange.TestCases#cases") void coinChange(int[] coins, int amount, int expected) { - assertEquals(expected, new SolutionDp().coinChange(coins, amount)); + assertEquals(expected, new Solution().coinChange(coins, amount)); } } From dd08116d30a3f08a818afdcaeb096a09028ac1e7 Mon Sep 17 00:00:00 2001 From: Yam Borodetsky Date: Thu, 19 Feb 2026 00:58:16 +0500 Subject: [PATCH 9/9] Update Coin Change complexity and add Javadoc --- README.md | 16 ++++++++-------- .../codes/yam/leetcode/coinchange/Solution.java | 8 ++++++++ .../yam/leetcode/coinchange/SolutionNaive.java | 11 +++++++++++ 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 7b95eb9..7159331 100644 --- a/README.md +++ b/README.md @@ -6,14 +6,14 @@ My LeetCode solutions in Java, focused on clean code and optimal algorithms. ## Solutions -| #* | Problem | Difficulty | Time | Space | [Blind 75][blind-75] | -|-----------------|----------------------------------------------------------------------------------------------------------------------------------|------------|-------------------|--------|----------------------| -| [1][lc-1] | [Two Sum](src/main/java/codes/yam/leetcode/twosum/Solution.java) | Easy | `O(n log n)` | `O(n)` | Yes | -| [9][lc-9] | [Palindrome Number](src/main/java/codes/yam/leetcode/palindromenumber/Solution.java) | Easy | `O(log10(n) / 2)` | `O(1)` | No | -| [70][lc-70] | [Climbing Stairs](src/main/java/codes/yam/leetcode/climbingstairs/Solution.java) | Easy | `O(n)` | `O(1)` | Yes | -| [322][lc-322] | [Coin Change](src/main/java/codes/yam/leetcode/coinchange/Solution.java) | Medium | TBD | TBD | Yes | -| [746][lc-746] | [Min Cost Climbing Stairs](src/main/java/codes/yam/leetcode/mincostclimbingstairs/Solution.java) | Easy | `O(n)` | `O(1)` | No | -| [1653][lc-1653] | [Minimum Deletions to Make String Balanced](src/main/java/codes/yam/leetcode/minimumdeletionstomakestringbalanced/Solution.java) | Medium | `O(n)` | `O(1)` | No | +| #* | Problem | Difficulty | Time | Space | [Blind 75][blind-75] | +|-----------------|----------------------------------------------------------------------------------------------------------------------------------|------------|-------------------|-------------|----------------------| +| [1][lc-1] | [Two Sum](src/main/java/codes/yam/leetcode/twosum/Solution.java) | Easy | `O(n log n)` | `O(n)` | Yes | +| [9][lc-9] | [Palindrome Number](src/main/java/codes/yam/leetcode/palindromenumber/Solution.java) | Easy | `O(log10(n) / 2)` | `O(1)` | No | +| [70][lc-70] | [Climbing Stairs](src/main/java/codes/yam/leetcode/climbingstairs/Solution.java) | Easy | `O(n)` | `O(1)` | Yes | +| [322][lc-322] | [Coin Change](src/main/java/codes/yam/leetcode/coinchange/Solution.java) | Medium | `O(amount × n)` | `O(amount)` | Yes | +| [746][lc-746] | [Min Cost Climbing Stairs](src/main/java/codes/yam/leetcode/mincostclimbingstairs/Solution.java) | Easy | `O(n)` | `O(1)` | No | +| [1653][lc-1653] | [Minimum Deletions to Make String Balanced](src/main/java/codes/yam/leetcode/minimumdeletionstomakestringbalanced/Solution.java) | Medium | `O(n)` | `O(1)` | No | *Problem numbers link to LeetCode; problem names link to solution source. diff --git a/src/main/java/codes/yam/leetcode/coinchange/Solution.java b/src/main/java/codes/yam/leetcode/coinchange/Solution.java index ce18ac9..fe6c431 100644 --- a/src/main/java/codes/yam/leetcode/coinchange/Solution.java +++ b/src/main/java/codes/yam/leetcode/coinchange/Solution.java @@ -2,6 +2,14 @@ import java.util.Arrays; +/** + * Solution for the Coin Change problem. + * + *
      + *
    • Time Complexity: O(amount * n) where {@code n} is {@code coins.length} + *
    • Space Complexity: O(amount) + *
    + */ class Solution { int coinChange(int[] coins, int amount) { int[] dp = new int[amount + 1]; diff --git a/src/main/java/codes/yam/leetcode/coinchange/SolutionNaive.java b/src/main/java/codes/yam/leetcode/coinchange/SolutionNaive.java index d02d3b7..e4aeb59 100644 --- a/src/main/java/codes/yam/leetcode/coinchange/SolutionNaive.java +++ b/src/main/java/codes/yam/leetcode/coinchange/SolutionNaive.java @@ -1,5 +1,16 @@ package codes.yam.leetcode.coinchange; +/** + * Solution for the Coin Change problem. + * + *

    Naive bottom-up DP using {@code -1} as the sentinel for unreachable states. See {@link + * Solution} for the simplified version using {@code amount + 1} as infinity. + * + *

      + *
    • Time Complexity: O(amount * n) where {@code n} is {@code coins.length} + *
    • Space Complexity: O(amount) + *
    + */ class SolutionNaive { int coinChange(int[] coins, int amount) { if (amount == 0) return 0;