0

I'm looking for a different way to solve coin change problem using modulus. Most solutions refer to use of dynamic memory to solve this.

Example: 

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.

Input: coins = [1, 2, 5], amount = 11
Output: 3 
Explanation: 11 = 5 + 5 + 1

The goal is to create a solution using modulus instead.

Here is what I've tried so far. I'm wondering if my variable should be initialized to something other than 0 or I'm updating in the wrong part of the code block.

class Solution {
public:

    int coinChange(vector<int>& coins, int amount) {

        int pieces = 0;
        int remainder = 0;

        for(int i = coins.size()-1; i = 0; i--) {
            if (amount % coins[i] == 0)
            {
                pieces += amount/coins[i];
            } else {
                pieces += amount/coins[i];
                remainder = amount%coins[i];
                amount = remainder;
            }
        }
        return pieces;
    }
}

I'm expecting the output as above. Stuck and not sure what else to try to get this to work.

  • Unrelated: consider using reverse iterators instead of indexing in the `for` loop. The logic is a bit easier and you get to wow the interviewer by knowing what iterators are. – user4581301 Nov 02 '19 at 00:12
  • 7
    You're describing a greedy approach to this problem which isn't always correct for denominations different from the US currency. For example, given the denominations `{1, 5, 8, 10}` and a total amount of 13 your algorithm might use the coins `{10, 1, 1, 1}` for a total of 4 coins when a more optimal solution of `{8, 5}` exists. – eesiraed Nov 02 '19 at 00:14
  • oh ok, I see what you're getting at there. Thanks. – RedPandaRevolt Nov 02 '19 at 00:17
  • 1
    You've described the goal of your code, included your code, and provided the expected output. That much is good (and it's more than many questions provide). One key piece you are missing, though, is your actual output. Without that, I'll just assume you got your expected output, so there's no question to answer. – JaMiT Nov 02 '19 at 00:29
  • If you are looking for a recursive solution that yields correct results, consult [a similar answer](https://stackoverflow.com/a/58466345/104458) I gave for Python a couple of weeks ago. (It initially got a few down votes because of a mistake I originally made - but it works now). It's an easy port to C++. – selbie Nov 02 '19 at 00:54
  • read about knapsack... – ChuckCottrill Nov 02 '19 at 03:54

1 Answers1

0

I understand what you're trying to do, but your code isn't actually going to accomplish what you think it will. Here's a breakdown of your code:

int coinChange(vector<int>& coins, int amount) {

    // Minimum number of coins to sum to 'amount'
    int pieces = 0;
    int remainder = 0;

    // Assuming 'coins' is a non-decreasing vector of ints,
    // iterate over all coins, starting from the larger ones,
    // ending with the smaller ones. This makes sense, as it
    // will use more coins of higher value, implying less
    // coins being used
    for(int i = coins.size()-1; i = 0; i--) {
        // If what's left of the original amount is
        // a multiple of the current coin, 'coins[i]',
        if (amount % coins[i] == 0)
        {
            // Increase the number of pieces by the number
            // of current coins that would satisfy it
            pieces += amount/coins[i];

            // ERROR: Why are you not updating the remaining amount?
        } else {
            // What's left of the original amount is NOT
            // a multiple of the current coin, so account
            // for as much as you can, and leave the remainder
            pieces += amount/coins[i];
            remainder = amount%coins[i];
            amount = remainder;
        }
    }

    // ERROR: What if amount != 0? Should return -1
    return pieces;
}

If you fixed the ERRORs I mentioned above, the function would work ASSUMING that all ints in coins behave as the following:

  1. If a coin, s, is smaller than another coin, l, then l must be a multiple of s.
  2. Every coin has to be >= 1.

Proof of 1:

If a coin, s, is smaller than another coin, l, but l is not a multiple of s, using l as one of the coins in your solution might be a bad idea. Let's consider an example, where coins = [4, 7], and amount = 8. You will iterate over coins in non-increasing order, starting with 7. 7 fits into 8, so you will say that pieces = 1, and amount = 1 remains. Now, 4 doesn't fit into amount, so you don't add it. Now the for-loop is over, amount != 0, so you fail the function. However, a working solution would have been two coins of 4, so returning pieces = 2.

Proof of 2:

If a coin, c is < 1, it can be 0 or less. If c is 0, you will divide by 0 and throw an error. Even more confusingly, if you changed your code you could add an infinite amount of coins valued 0.

If c is negative, you will divide by a negative, resulting in a negative amount, breaking your logic.

Josh Evans
  • 567
  • 1
  • 5
  • 16