Question - 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.Infinite supply of coin is there.
My Approach - I have followed the top-down approach but with memoization using map stl, I am getting TLE. Please help in finding out the error and estimating the time complexity.
Here is my code -
// for example coins v = {1,2} and W = 2 then possible solutions are -
// (2) or (1, 1), therefore minimum number of coins required is 1.
// Below is the function calculating the minimum number of coins required for change
int minCoinChange(vector<int> &v, int start, int W, unordered_map<string, int> &lookup){
// v denoting the vector conataining coins with given denomination
// start denoting the start index i.e. 0(initially)
// W denoting the required change
// lookup is map stl for storing values.
// base cases
if(W<0){
return INT_MAX;
}
if(W == 0){
return 0;
}
if(start >= v.size()){
return INT_MAX;
}
// for memoization creating the "key"
string key = to_string(start) + '|' + to_string(W);
// if the key is not found in map then go inside if
if(lookup.find(key) == lookup.end()){
int excl = minCoinChange(v, start+1, W, lookup); // if element is excluded
int incl = 1 + minCoinChange(v, start, W - v[start], lookup); if element is included
lookup[key] = min(incl, excl); // calculating minimum number of coins required and storing in map
}
// if key is already there then return value stored in map
return lookup[key];
}
First of all, unordered_map
has a worst case O(n)
look up time. There are ways to optimize unordered_map
performance like reserving number of buckets with map.reserve(n)
with n
being the number of unique items you expect to have in the map.
You can use map
instead which has worst case O(log(n))
look up time, but since the time complexity of that algorithm is O(n * W)
your n
and W
will be small enough to fit in an array and then you will have O(1)
look up instead.
Below is modification of your function to use array look up instead:
int minCoinChange(vector<int> &v, int start, int W, vector<vector<int>> &lookup){
// v denoting the vector conataining coins with given denomination
// start denoting the start index i.e. 0(initially)
// W denoting the required change
// lookup is 2d vector for storing already computed values.
// base cases
if (W<0) {
return 1e9;
}
if (W == 0) {
return 0;
}
if (start >= v.size()) {
return 1e9;
}
// if this state wasn't computed before
if (lookup[start][W] == -1) {
int excl = minCoinChange(v, start+1, W, lookup); // if element is excluded
int incl = 1 + minCoinChange(v, start, W - v[start], lookup); // if element is included
lookup[start][W] = min(incl, excl); // calculating minimum number of coins required and storing in map
}
// return the saved value
return lookup[start][W];
}
Note:
For base cases, instead of using INT_MAX
which will overflow if you add 1
to it, use something like 10^9
.