-
Notifications
You must be signed in to change notification settings - Fork 101
/
Copy pathCoinChange322.java
137 lines (118 loc) · 3.91 KB
/
CoinChange322.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/**
* You are given coins of different denominations and a total amount of money
* amount. Write a function to compute the fewest number of coins that you
* need to make up that amount. If that amount of money cannot be made up by
* any combination of the coins, return -1.
*
* Example 1:
* coins = [1, 2, 5], amount = 11
* return 3 (11 = 5 + 5 + 1)
*
* Example 2:
* coins = [2], amount = 3
* return -1.
*
* Note:
* You may assume that you have an infinite number of each kind of coin.
*
*/
public class CoinChange322 {
public int coinChange(int[] coins, int amount) {
Arrays.sort(coins);
return helper(coins.length-1, coins, amount);
}
private int helper(int idx, int[] coins, int left) {
if (idx < 0) return -1;
int curr = coins[idx];
int multi = left / curr;
int currLeft = left % curr;
if (currLeft == 0) return multi;
int res = Integer.MAX_VALUE;
int reduce = multi;
int newLeft = currLeft;
while(reduce >= 0) {
int temp = helper(idx-1, coins, newLeft);
if (temp != -1) res = Math.min(res, temp+reduce);
reduce--;
newLeft = newLeft + curr;
}
return (res == Integer.MAX_VALUE) ? -1 : res;
}
/**
* https://leetcode.com/problems/coin-change/solution/
*/
public int coinChange2(int[] coins, int amount) {
if (amount < 1) return 0;
return dp(coins, amount, new int[amount]);
}
private int dp(int[] coins, int left, int[] amounts) {
if (left < 0) return -1;
if (left == 0) return 0;
if (amounts[left - 1] != 0) return amounts[left - 1];
int res = Integer.MAX_VALUE;
for (int i=0; i<coins.length; i++) {
int next = dp(coins, left-coins[i], amounts);
if (next >= 0 && next < res)
res = next +1;
}
amounts[left - 1] = (res == Integer.MAX_VALUE) ? -1 : res;
return amounts[left - 1];
}
/**
* https://leetcode.com/problems/coin-change/solution/
*/
public int coinChange3(int[] coins, int amount) {
int[] dp = new int[amount + 1];
Arrays.fill(dp, amount + 1);
dp[0] = 0;
for (int i=1; i<=amount; i++) {
for (int j=0; j<coins.length; j++) {
if (coins[j] <= i) {
dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
}
}
}
return dp[amount] > amount ? -1 : dp[amount];
}
public int coinChange4(int[] coins, int amount) {
int[] dp = new int[amount + 1];
for (int i=1; i<=amount; i++) {
int t = Integer.MAX_VALUE;
for (int c: coins) {
if (i >= c && dp[i - c] != -1) {
t = Math.min(t, dp[i - c] + 1);
}
}
dp[i] = t == Integer.MAX_VALUE ? -1 : t;
}
return dp[amount];
}
public int coinChange5(int[] coins, int amount) {
int[] dp = new int[amount + 1];
Arrays.fill(dp, amount + 1);
dp[0] = 0;
for (int c: coins) {
for (int i=c; i<=amount; i++) {
dp[i] = Math.min(dp[i], dp[i - c] + 1);
}
}
return (dp[amount] == amount + 1) ? -1 : dp[amount];
}
public int coinChange6(int[] coins, int amount) {
Arrays.sort(coins);
int[] res = new int[]{amount + 1};
coinChange(coins, amount, coins.length - 1, res, 0);
return (res[0] == amount + 1) ? -1 : res[0];
}
public void coinChange(int[] coins, int amount, int idx, int[] res, int num) {
if (amount == 0) {
res[0] = Math.min(res[0], num);
return;
}
if (idx < 0) return;
int k = amount / coins[idx];
for (int j=k; j>=0 && num + j < res[0]; j--) {
coinChange(coins, amount - j * coins[idx], idx-1, res, num + j);
}
}
}