-
Notifications
You must be signed in to change notification settings - Fork 33
/
CoinChangeNumberOfWays.java
89 lines (62 loc) · 3.17 KB
/
CoinChangeNumberOfWays.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
/*
https://www.geeksforgeeks.org/coin-change-dp-7/
Given a value N, if we want to make change for N cents, and we have infinite supply of each of S = { S1, S2, .. , Sm} valued coins, how many ways can we make the change? The order of coins doesn’t matter.
For N = 4 and S = {1,2,3}, there are four solutions: {1,1,1,1},{1,1,2},{2,2},{1,3}. So output should be 4.
For N = 10 and S = {2, 5, 3, 6}, there are five solutions: {2,2,2,2,2}, {2,2,3,3}, {2,2,6}, {2,3,5} and {5,5}. So the output should be 5.
OPTIMAL SUBSTRUCTURE
Here S[] = array of coin denomination
m = number of coins (S.length)
n = Given sum(coin) whose change is to be calculated
To count the total number of solutions, we can divide all set solutions into two sets.
1) Solutions that do not contain mth coin (or Sm). ==> count(S[], m-1, n) ==> EXCLUDE CURRENT COIN
2) Solutions that contain at least one Sm. ==> count(S[], m, n-S[m]) ==> INCLUDE CURRENT COIN
count(S[], m, n) = count(S[], m-1, n) + count(S[], m, n-Sm)
*/
//RECURSIVE SOLUTION - COUNTS DISTINCT SOLUTION SETS
public int coinChangeWays(int coins[], int index, int coinVal){
if(coinVal == 0) return 1;
else if(coinVal < 0) return 0;
else if(coinVal > 0 && index <= 0)
else return coinChangeWays(coins, index-1, coinVal) + coinChangeWays(coins, index, coinVal-coins[index-1]);
}
//DYNAMIC PROGRAMMING - BOTTOM UP APPROACH
public int coinChangeWays(int coins[], int numOfCoins, int coinVal){
//ways[i][j] indicates the number of ways in which a value=j can be changed(formed) by considering coins from [1...i]
int ways[][] = new int[numOfCoins+1][coinVal+1];
for(int i=0 ; i <= numOfCoins ; i++) ways[i][0] = 1;
for(int i=1 ; i <= numOfCoins ; i++){
for(int j=1 ; j <= coinVal ; j++){
//include current coin if [currentVal(j)-currentCoinValue(coins[i-1]) >= 0]
//Basically check, if it is possible to include coin or not
if(j >= coins[i-1]){
//include coin + exclude coin
ways[i][j] = ways[i-1][j] + ways[i][j - coins[i-1]];
}
//exclude current coin - value(j) remains same
else ways[i][j] = ways[i-1][j];
}
}
return ways[numOfCoins][coinVal];
}
/*
Time Complexity - O(numOfCoins * coinVal)
Space Complexity - O(numOfCoins * coinVal)
*/
//DYNAMIC PROGRAMMING - SPACE OPTIMIZED BOTTOM APPROACH
public int coinChangeWays(int coins[], int coinVal){
int ways[] = new int[coinVal+1];
ways[0] = 1;
for(int coinIndex=0 ; coinIndex < coins.length ; coinIndex++){
//currval starts from coins[coinIndex] because for values smaller than coins[coinIndex],
//ways[coinIndex] remains the same ==> excluding coinIndex
for(int currVal = coins[coinIndex] ; currVal <= coinVal ; currVal++){
//including coins[coinIndex]
ways[coinIndex] += ways[currVal - coins[coinIndex]];
}
}
return ways[coinVal];
}
/*
Time Complexity - O(numOfCoins * coinVal)
Space Complexity - O(coinVal)
*/