Find the least number of coins required that can make any change from 1 to 99 cents

后端 未结 27 2258
生来不讨喜
生来不讨喜 2020-12-07 10:08

Recently I challenged my co-worker to write an algorithm to solve this problem:

Find the least number of coins required that can make any change from

27条回答
  •  被撕碎了的回忆
    2020-12-07 10:23

    The task

    Find the least number of coins required, that can make any change from 1 to 99 cent.
    

    differs from the task

    For each single change from 1 to 99 cent, find the least number of coins required.
    

    because the solution might be a complete different multiset of coins.

    Suppose you have not (1), (5), (10), and (25) cent coins, but (1), (3), (5), and (17) cent coins: To make the change for 5, you only need one (5) coin; but for all changes from 1 to 5 you need two (1) coins and one (3) coin, not any (5) coin.

    The greedy algorithm iterates from the smallest value to the largest, concerning the change values and coin values:

    With 1x(1) you get all change values below 2.
    
    To make a change of 2, you need an additional coin,
    which could have any value up to 2;
    choose greedy -> choose the largest -> (1).
    
    With 2x(1) you get all change values below 3.
    
    To make a change of 3, you need an additional coin,
    which could have any value up to 3;
    choose greedy -> choose the largest -> (3).
    
    With 2x(1)+1x(3) you get all change values below 6.
    
    To make a change of 6, you need an additional coin,
    which could have any value up to 6;
    choose greedy -> choose the largest -> (5).
    
    and so on...
    

    That is in Haskell:

    coinsforchange [1,3,5,17] 99
    where
        coinsforchange coins change = 
            let f (coinssofar::[Int],sumsofar::Int) (largestcoin::Int,wanttogoto::Int) = 
                    let coincount=(max 0 (wanttogoto-sumsofar+largestcoin-1))`div`largestcoin
                     in (replicate coincount largestcoin++coinssofar,sumsofar+coincount*largestcoin)
             in foldl f ([],0) $ zip coins $ tail [c-1|c<-coins] ++ [change]
    

    And in C++:

    void f(std::map &coinssofar,int &sumsofar, unsigned largestcoin, int wanttogoto)
    {
        int x = wanttogoto - sumsofar + largestcoin - 1;
        coinssofar[largestcoin] = (x>0) ? (x / largestcoin) : 0;
        //returns coinssofar and sumsofar;
    }
    std::map coinsforchange(const std::list &coins, int change)
    {
        std::map coinssofar;
        int sumsofar=0;
        std::list::const_iterator coin = coins.begin();
        unsigned largestcoin = *coin;
        for( ++coin ; coin!=coins.end() ; largestcoin=*(coin++))
            f(coinssofar,sumsofar,largestcoin,(*coin) - 1);
        f(coinssofar,sumsofar,largestcoin,change);
        return coinssofar;
    }
    

提交回复
热议问题