15
15
16
16
import java .util .ArrayList ;
17
17
import java .util .List ;
18
+ import java .util .Optional ;
18
19
19
20
public class CoinChange {
20
21
21
22
public static class Solution {
22
- int minCoins ;
23
+ // Contains the minimum number of coins to make a certain amount, if an optimal solution exists.
24
+ Optional <Integer > minCoins = Optional .empty ();
25
+
26
+ // The coins selected as part of the optimal solution.
23
27
List <Integer > selectedCoins = new ArrayList <Integer >();
24
28
}
25
29
26
30
// TODO(william): setting an explicit infinity could lead to a wrong answer for
27
31
// very large values. Prefer to use null instead.
28
32
private static final int INF = Integer .MAX_VALUE / 2 ;
29
33
30
- private static void p (int [][] dp ) {
31
- for (int [] r : dp ) {
32
- for (int v : r ) {
33
- System .out .printf ("%4d, " , v == INF ? -1 : v );
34
- }
35
- System .out .println ();
36
- }
37
- }
38
-
39
34
public static Solution coinChange (int [] coins , final int n ) {
40
35
if (coins == null ) throw new IllegalArgumentException ("Coins array is null" );
41
36
if (coins .length == 0 ) throw new IllegalArgumentException ("No coin values :/" );
@@ -70,11 +65,10 @@ public static Solution coinChange(int[] coins, final int n) {
70
65
71
66
Solution solution = new Solution ();
72
67
73
- // The amount we wanted to make cannot be made :/
74
- if (dp [m ][n ] == INF ) {
75
- solution .minCoins = -1 ;
68
+ if (dp [m ][n ] != INF ) {
69
+ solution .minCoins = Optional .of (dp [m ][n ]);
76
70
} else {
77
- solution . minCoins = dp [ m ][ n ] ;
71
+ return solution ;
78
72
}
79
73
80
74
for (int change = n , coinIndex = m ; coinIndex > 0 ; ) {
@@ -91,7 +85,7 @@ public static Solution coinChange(int[] coins, final int n) {
91
85
return solution ;
92
86
}
93
87
94
- public static int coinChangeSpaceEfficient (int [] coins , int n ) {
88
+ public static Solution coinChangeSpaceEfficient (int [] coins , int n ) {
95
89
if (coins == null ) throw new IllegalArgumentException ("Coins array is null" );
96
90
97
91
// Initialize table and set everything to infinity except first cell
@@ -107,11 +101,31 @@ public static int coinChangeSpaceEfficient(int[] coins, int n) {
107
101
}
108
102
}
109
103
110
- // The amount we wanted to make cannot be made :/
111
- if (dp [n ] == INF ) return -1 ;
104
+ Solution solution = new Solution ();
105
+ if (dp [n ] != INF ) {
106
+ solution .minCoins = Optional .of (dp [n ]);
107
+ } else {
108
+ return solution ;
109
+ }
110
+
111
+ for (int i = n ; i > 0 ; ) {
112
+ int selectedCoinValue = INF ;
113
+ int cellWithFewestCoins = dp [i ];
114
+ for (int coin : coins ) {
115
+ if (i - coin < 0 ) {
116
+ continue ;
117
+ }
118
+ if (dp [i - coin ] < cellWithFewestCoins ) {
119
+ cellWithFewestCoins = dp [i - coin ];
120
+ selectedCoinValue = coin ;
121
+ }
122
+ }
123
+ solution .selectedCoins .add (selectedCoinValue );
124
+ i -= selectedCoinValue ;
125
+ }
112
126
113
127
// Return the minimum number of coins needed
114
- return dp [ n ] ;
128
+ return solution ;
115
129
}
116
130
117
131
// The recursive approach has the advantage that it does not have to visit
@@ -142,6 +156,23 @@ private static int coinChangeRecursive(int n, int[] coins, int[] dp) {
142
156
return dp [n ] = (minCoins == INF ) ? -1 : minCoins ;
143
157
}
144
158
159
+ // DP table print function. Used for debugging.
160
+ private static void p (int [][] dp ) {
161
+ for (int [] r : dp ) {
162
+ for (int v : r ) {
163
+ System .out .printf ("%4d, " , v == INF ? -1 : v );
164
+ }
165
+ System .out .println ();
166
+ }
167
+ }
168
+
169
+ private static void p (int [] dp ) {
170
+ for (int v : dp ) {
171
+ System .out .printf ("%4d, " , v == INF ? -1 : v );
172
+ }
173
+ System .out .println ();
174
+ }
175
+
145
176
public static void main (String [] args ) {
146
177
// example1();
147
178
// example2();
@@ -152,10 +183,10 @@ public static void main(String[] args) {
152
183
private static void example4 () {
153
184
int n = 11 ;
154
185
int [] coins = {2 , 4 , 1 };
155
- System .out .println (coinChange (coins , n ).minCoins );
186
+ // System.out.println(coinChange(coins, n).minCoins);
156
187
System .out .println (coinChangeSpaceEfficient (coins , n ));
157
- System .out .println (coinChangeRecursive (coins , n ));
158
- System .out .println (coinChange (coins , n ).selectedCoins );
188
+ // System.out.println(coinChangeRecursive(coins, n));
189
+ // System.out.println(coinChange(coins, n).selectedCoins);
159
190
}
160
191
161
192
private static void example1 () {
0 commit comments