Open In App

Coin change problem with limited coins

Last Updated : 04 Oct, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given three integers n, k, target, and an array of coins[] of size n. Find if it is possible to make a change of target cents by using an infinite supply of each coin but the total number of coins used must be exactly equal to k.

Examples:

Input: n = 5, k = 3, target = 11, coins = {1, 10, 5, 8, 6}
Output: 1
Explanation: 2 coins of 5 and 1 coin of 1 can be used to make a change of 11 i.e. 11 => 5 + 5 + 1.

Input: n = 3, k = 5, target = 25, coins = {7, 2, 4}
Output: 1
Explanation: 3 coins 7, 2 coins of 2 can be used to make a change of 25 i.e. 25 => 7+7+7+2+2.

Naive Approach :

The basic way to solve this problem is to generate all possible combinations by using a recursive approach.

Below are the steps involved in the implementation of the code:

  • If target == 0 and k == 0, return true
  • If n == 0 or target < 0 or k < 0, return false 
  • Otherwise, the result is true if either of the following conditions is satisfied:
    • Include the last coin and recursively check if it is possible to make the remaining target using k-1 coins.
    • Exclude the last coin and recursively check if it is possible to make the target using the remaining n-1 coins and k coins.

below is the code implementation of the above code:

C++




#include <bits/stdc++.h>
using namespace std;
 
// Function to check if it is possible to make a change of
// target cents using exactly k coins from the given coins
// array of size n
bool canMakeChange(int target, int k, int coins[], int n)
{
    // If target and k are both 0, then we have found a
    // valid combination of coins
    if (target == 0 && k == 0) {
        return true;
    }
    // If n becomes 0 or target or k becomes negative, then
    // the current combination of coins is not valid
    if (n == 0 || target < 0 || k < 0) {
        return false;
    }
    // we can either include the current coin or exclude it
    // We check if it is possible to make the change by
    // including the current coin or excluding it
    return canMakeChange(target - coins[n - 1], k - 1,
                         coins, n)
           || canMakeChange(target, k, coins, n - 1);
}
 
int main()
{
    int n = 5;
    int k = 3;
    int target = 11;
    int coins[] = { 1, 10, 5, 8, 6 };
 
    // Check if it is possible to make the change using 'k'
    // coins from the 'coins' array to get 'target' cents
    bool result = canMakeChange(target, k, coins, n);
 
    // Print the result
    if (result) {
        cout << "1" << endl;
    }
    else {
        cout << "0" << endl;
    }
    return 0;
}


Java




import java.util.Arrays;
 
class GFG {
     
    // Function to check if it is possible to make a change of
    // target cents using exactly k coins from the given coins
    // array of size n
    static boolean canMakeChange(int target, int k, int[] coins, int n) {
        // If target and k are both 0, then we have found a
        // valid combination of coins
        if (target == 0 && k == 0) {
            return true;
        }
        // If n becomes 0 or target or k becomes negative, then
        // the current combination of coins is not valid
        if (n == 0 || target < 0 || k < 0) {
            return false;
        }
        // we can either include the current coin or exclude it
        // We check if it is possible to make the change by
        // including the current coin or excluding it
        return canMakeChange(target - coins[n - 1], k - 1, coins, n)
                || canMakeChange(target, k, coins, n - 1);
    }
     
    public static void main(String[] args) {
        int n = 5;
        int k = 3;
        int target = 11;
        int[] coins = { 1, 10, 5, 8, 6 };
 
        // Check if it is possible to make the change using 'k'
        // coins from the 'coins' array to get 'target' cents
        boolean result = canMakeChange(target, k, coins, n);
 
        // Print the result
        if (result) {
            System.out.println("1");
        } else {
            System.out.println("0");
        }
    }
}
 
// This code is contributed by shivamgupta0987654321


Python3




# python Implementation
 
# Function to check if it is possible to make a change of
# target cents using exactly k coins from the given coins
# array of size n
def can_make_change(target, k, coins, n):
    # If target and k are both 0, then we have found a
    # valid combination of coins
    if target == 0 and k == 0:
        return True
    # If n becomes 0 or target or k becomes negative, then
    # the current combination of coins is not valid
    if n == 0 or target < 0 or k < 0:
        return False
    # we can either include the current coin or exclude it
    # We check if it is possible to make the change by
    # including the current coin or excluding it
    return can_make_change(target - coins[n - 1], k - 1, coins, n) or can_make_change(target, k, coins, n - 1)
 
def main():
    n = 5
    k = 3
    target = 11
    coins = [1, 10, 5, 8, 6]
 
    # Check if it is possible to make the change using 'k'
    # coins from the 'coins' array to get 'target' cents
    result = can_make_change(target, k, coins, n)
 
    # Print the result
    if result:
        print("1")
    else:
        print("0")
 
if __name__ == "__main__":
    main()


C#




// C# Implementation
using System;
 
class GFG {
     
// Function to check if it is possible to make a change of
// target cents using exactly k coins from the given coins
// array of size n
static bool canMakeChange(int target, int k, int[] coins, int n)
{
    // If target and k are both 0, then we have found a
    // valid combination of coins
    if (target == 0 && k == 0) {
        return true;
    }
    // If n becomes 0 or target or k becomes negative, then
    // the current combination of coins is not valid
    if (n == 0 || target < 0 || k < 0) {
        return false;
    }
    // we can either include the current coin or exclude it
    // We check if it is possible to make the change by
    // including the current coin or excluding it
    return canMakeChange(target - coins[n - 1], k - 1,
                        coins, n)
        || canMakeChange(target, k, coins, n - 1);
}
 
public static int Main()
{
    int n = 5;
    int k = 3;
    int target = 11;
    int[] coins = { 1, 10, 5, 8, 6 };
 
    // Check if it is possible to make the change using 'k'
    // coins from the 'coins' array to get 'target' cents
    bool result = canMakeChange(target, k, coins, n);
 
    // Print the result
    if (result) {
        Console.WriteLine("1");
    }
    else {
        Console.WriteLine("0");
    }
    return 0;
}
 
}
 
// This code is contributed by Utkarsh Kumar


Javascript




// JavaScript Implementation
 
// Function to check if it is possible to make a change of
// target cents using exactly k coins from the given coins
// array of size n
function can_make_change(target, k, coins, n) {
    // If target and k are both 0, then we have found a
    // valid combination of coins
    if (target === 0 && k === 0) {
        return true;
    }
    // If n becomes 0 or target or k becomes negative, then
    // the current combination of coins is not valid
    if (n === 0 || target < 0 || k < 0) {
        return false;
    }
    // we can either include the current coin or exclude it
    // We check if it is possible to make the change by
    // including the current coin or excluding it
    return can_make_change(target - coins[n - 1], k - 1, coins, n) || can_make_change(target, k, coins, n - 1);
}
 
let n = 5;
let k = 3;
let target = 11;
let coins = [1, 10, 5, 8, 6];
 
// Check if it is possible to make the change using 'k'
// coins from the 'coins' array to get 'target' cents
let result = can_make_change(target, k, coins, n);
 
// Print the result
if (result) {
    console.log("1");
} else {
    console.log("0");
}
 
// This code is contributed by Tapesh(tapeshdua420)


Output

1












Time Complexity : O(2^(k+n))
Space Complexity :  O(k+n)

Efficient Approach: This can be solved with the following idea:

The approach used is a dynamic programming approach, The approach works by building a table of subproblems using a two-dimensional boolean array. The approach iterates over all values of i from 1 to target and all values of j from 0 to K. For each subproblem dp[i][j], the algorithm checks whether any of the coins in the array can be used to add up to i while using j-1 coins to add up to the remaining value. If so, the subproblem is marked as solved by setting dp[i][j] = true. The algorithm returns dp[target][K] as the solution to the original problem. 

Below are the steps involved in the implementation of the code:

  • Initialize a two-dimensional boolean array dp of size (target+1) x (K+1).
  • Set the base case dp[0][0] = true.
  • For i from 1 to target and j from 0 to K, do the following:
    • For each coin in the array coins, do the following:
      • If the current coin denomination is less than or equal to i, and j > 0 (i.e., there are still coins remaining to be used), and dp[i-coin][j-1] is true, then set dp[i][j] to true and break out of the loop over coins.
  • Return dp[target][K] as the solution to the original problem.

below is the code implementation of the above code:

C++




// Nikunj Sonigara
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to check whether target can be achieved by K coins
bool makeChanges(int N, int K, int target, vector<int>& coins) {
    vector<vector<bool>> dp(target + 1, vector<bool>(K + 1, false));
    dp[0][0] = true;
 
    for (int i = 1; i <= target; i++) {
        for (int j = 0; j <= K; j++) {
            for (int coin : coins) {
                if (coin <= i && j > 0 && dp[i - coin][j - 1]) {
                    dp[i][j] = true;
                    break;
                }
            }
        }
    }
 
    // Return the result
    return dp[target][K];
}
 
int main() {
    int N = 5;
    int K = 3;
    int target = 11;
    vector<int> coins = {1, 10, 5, 8, 6};
 
    // Function call
    bool result = makeChanges(N, K, target, coins);
    if (result) {
        cout << '1' << endl;
    } else {
        cout << '0' << endl;
    }
 
    return 0;
}


Java




// java code for the above approach:
import java.util.*;
 
public class CoinChangeProblem {
 
    // Function to check whether target
    // can be achieved by K coins
    public static boolean
    makeChanges(int N, int K, int target, int[] coins)
    {
        boolean[][] dp = new boolean[target + 1][K + 1];
        dp[0][0] = true;
 
        for (int i = 1; i <= target; i++) {
            for (int j = 0; j <= K; j++) {
                for (int coin : coins) {
                    if (coin <= i && j > 0
                        && dp[i - coin][j - 1]) {
                        dp[i][j] = true;
                        break;
                    }
                }
            }
        }
 
        // Return the result
        return dp[target][K];
    }
 
    // Driver codes
    public static void main(String[] args)
    {
        int N = 5;
        int K = 3;
        int target = 11;
        int[] coins = { 1, 10, 5, 8, 6 };
 
        // Function call
        boolean result = makeChanges(N, K, target, coins);
        if (result == true) {
            System.out.println('1');
        }
        else {
            System.out.println('0');
        }
    }
}


Python




# Nikunj Sonigara
 
def make_changes(N, K, target, coins):
    dp = [[False for _ in range(K + 1)] for _ in range(target + 1)]
    dp[0][0] = True
 
    for i in range(1, target + 1):
        for j in range(K + 1):
            for coin in coins:
                if coin <= i and j > 0 and dp[i - coin][j - 1]:
                    dp[i][j] = True
                    break
 
    # Return the result
    return dp[target][K]
 
N = 5
K = 3
target = 11
coins = [1, 10, 5, 8, 6]
 
# Function call
result = make_changes(N, K, target, coins)
if result:
    print('1')
else:
    print('0')


C#




using System;
 
public class CoinChangeProblem
{
    // Function to check whether target
    // can be achieved by K coins
    public static bool MakeChanges(int N, int K, int target, int[] coins)
    {
        bool[,] dp = new bool[target + 1, K + 1];
        dp[0, 0] = true;
        for (int i = 1; i <= target; i++)
        {
            for (int j = 0; j <= K; j++)
            {
                foreach (int coin in coins)
                {
                    if (coin <= i && j > 0 && dp[i - coin, j - 1])
                    {
                        dp[i, j] = true;
                        break;
                    }
                }
            }
        }
        // Return the result
        return dp[target, K];
    }
    // Driver codes
    public static void Main(string[] args)
    {
        int N = 5;
        int K = 3;
        int target = 11;
        int[] coins = { 1, 10, 5, 8, 6 };
        // Function call
        bool result = MakeChanges(N, K, target, coins);
        if (result == true)
        {
            Console.WriteLine('1');
        }
        else
        {
            Console.WriteLine('0');
        }
    }
}


Javascript




// Nikunj Sonigara
 
function makeChanges(N, K, target, coins) {
    const dp = new Array(target + 1);
    for (let i = 0; i <= target; i++) {
        dp[i] = new Array(K + 1).fill(false);
    }
    dp[0][0] = true;
 
    for (let i = 1; i <= target; i++) {
        for (let j = 0; j <= K; j++) {
            for (const coin of coins) {
                if (coin <= i && j > 0 && dp[i - coin][j - 1]) {
                    dp[i][j] = true;
                    break;
                }
            }
        }
    }
 
    // Return the result
    return dp[target][K];
}
 
const N = 5;
const K = 3;
const target = 11;
const coins = [1, 10, 5, 8, 6];
 
// Function call
const result = makeChanges(N, K, target, coins);
if (result) {
    console.log('1');
} else {
    console.log('0');
}


Output

1












Time Complexity: O(NKT)
Auxiliary Space: O(NKT)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads