leetcode 322 coins Exchange


1. Topic

  1. Change exchange
    given coins of different denominations of coins and a total amount of amount. We can write a function to calculate the minimum number of coins needed to make up the total amount. If there is no combination can be composed of any of a total amount of coins, return -1.

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

Example 2:
Input: coins = [2], amount = 3
Output: -1
Note:
You can think of each coin number is unlimited.

2. Solution

2.1. Brute force

Brute force is the essence of a program a try, if the conditions are met that the number of coins used in the record, and then from the minimum value.

2.1.1. Brute force 1

Note: do not need to be exhaustive of all combinations, the combination of large numbers beginning, a number of coins is determined as the minimum effective combination filter can reduce the number of recursive invalid;

    coinChange_1 DEF (Self, Coins, AMOUNT): 
        "" " 
        brute force 
        recursion 
        def _helper (coins, num, leftamount , cur_coins_list): 
        recursive function, coins: coin pool; num: subscript; leftamount: remaining amount of money; cur_coins_list: sequence current coin 
        time complexity: O (S ^ N); because each coin may have up to the worst case S / Ci one; 
        therefore the number of possible combinations of S / C1 * S / C2 * S / C3 ... ... S / Cn = S ^ N / C1 * C2 * C3 ...... Cn 
        simplify what is ^ N S 
        S is the amount, N is the number of coin types. 
        space complexity: O (N) worst case , the maximum depth of recursion is N. : 
        param coins: 
        : param AMOUNT: 
        : return: 
        "" " 
        Assert and coins None Not AMOUNT iS> 0, 'error value.' 
        mincount AMOUNT +. 1 = 
        # coins sorted by inversion large to small 
        Coins = List (the reversed (Coins ))

        # 递归函数
        def _helper(coins, num, leftamount, cur_coins_list):
            nonlocal mincount
            cur_coins_list.append(coins[num])

            length = len(cur_coins_list)
            if leftamount == 0:
                if length < mincount:
                    mincount = length
            elif leftamount > 0:
                if length >= mincount:
                    return
                for i in range(num, len(coins)):
                    _helper(coins, i, leftamount-coins[i], cur_coins_list[:])

        for x in range(len(coins)):
            _helper(coins, x, amount - coins[x], [])

        return -1 if mincount > amount else mincount

2.1.2. Brute force 2

The same logic, another way.

    def coinChange_1_1(self, coins, amount):
        """
        暴力穷举
        :param coins:
        :param amount:
        :return:
        """
        coins = list(reversed(coins))
        def _helper(index, coins, amount):
            if amount == 0: return 0

            if index < len(coins) and amount > 0:
                mincost = float('inf')
                for i in range(0, amount//coins[index]+1):
                    if amount >= i * coins[index]:
                        res = _helper(index+1, coins, amount - i * coins[index])
                        if res != -1:
                            mincost = min(mincost, res+i)
                return -1 if mincost == float('inf') else mincost
            return -1
        return _helper(0, coins, amount)

2.2. Bottom-up dynamic programming -1

One-dimensional array defined DP
DP [I] is a combination of the minimum number of coins required when as i, is then pushed forward to continue dp [i] = dp + 1 the minimum number of coins required [i-coin [j]] , +1 for using a coin [j] once.

principle:

Definition array dp [i] [j], it is the number of coins, the total amount of j, if j is defined as where element may be made of coins [0-i] in the composition of the coin, the coin is composed of a desired number of programs minimum. 

Provided dp [x] [y] solution exists, then dp [x] [y-coin [x]] least one solution (unless y is less than X),   
and dp [x] [y] of possible values dp [x] [y-coin [x]] + 1 ( the basis of the former added an extra coin [x])   
, however, note that the column j for all solutions in this amount on behalf of, so if dp [x-1] [y ] exists Solutions , means that the solution to the dp [x] [y] is also effective.  
Subject of the request is the minimum number of coins solution, it takes a minimum value both of:   
DP [X] [Y] = min (DP [X] [Y-COIN [X]], DP [. 1-X] [Y ]) 

of course, this is a two-dimensional array, but in practice is not concerned [x-2] and the data of the previous lines, but one by one backward iteration, it is possible to multiplex one-dimensional array is simplified.

Code:

    def coinChange_2(self, coins, amount):
        """
        动态规划
        从下至上
        :param coins:
        :param amount:
        :return:
        """
        dp = [float('inf')] * (amount + 1)
        dp[0] = 0

        for coin in coins:
            for x in range(coin, amount + 1):
                dp[x] = min(dp[x], dp[x-coin] + 1)
        return dp[amount] if dp[amount] != float('inf') else -1

2.3 top-down dynamic programming -2

Variant of the recursive method, using an array of records has been seeking solutions.

    def coinChange_2_2(self, coins, amount):
        """
        动态规划/递归穷举/回溯法
        自上而下
        :param coins:
        :param amount:
        :return:
        """
        def _helper(coins, leftamount, count_list):
            if leftamount < 0: return -1
            if leftamount == 0: return 0
            if count_list[leftamount-1] != 0: return count_list[leftamount - 1]
            mincount = float('inf')
            for x in range(len(coins)):
                res = _helper(coins, leftamount - coins[x], count_list)
                if res >= 0 and res < mincount:
                    mincount = res + 1
            count_list[leftamount - 1] = mincount if mincount != float('inf') else -1
            return count_list[leftamount - 1]

        return _helper(coins, amount, [0]*amount)

3. Code and test results

3.1 test code:

the __name__ == IF "__main__": 
    # instance solutions based 
    SO = Solution () 

    # Parameter setting 
    Li = [1,2,5,10,20] 
    para = (Li, 1 18) 

    test_func (SO, para) 
    Pass


3.2 Results:

A total of <4> of the method: [ 'coinChange_1_1', 'coinChange_1_2', 'coinChange_2_1', 'coinChange_2_2'] 

 ************************************************************ *************** 
the method of [1]: coinChange_1_1 
Description: brute force 
        recursion 
        def _helper (coins, num, leftamount , cur_coins_list): 
        recursive function, coins: coin pool; NUM: at standard; leftamount: remaining amount of money; cur_coins_list: sequence current coin 
        time complexity: O (S ^ N); because each coin may have up to S / Ci a worst case; 
        it may be the number of combinations of S / C1 * S / C2 * S / C3 ...... S / Cn = S ^ N / C1 * C2 * C3 ...... Cn 
        simplify what is ^ N S 
        S is the amount, N is the number of coin types. 
        Space complexity: worst case O (N), the maximum depth of recursion is N. 
        : param Coins is: 
        : param AMOUNT: 
        : return:

Description: brute force  
        : param Coins is: 
        : param AMOUNT:
        : return: 
The results: 9 

 ************************************** ** 
the method of [3]: coinChange_2_1 
Description: dynamic programming 
        from bottom to top 
        : param Coins: 
        : param AMOUNT: 
        : return: 
the results: 9 

 ******************** ******************** 
The method of [4]: coinChange_2_2 
Description: dynamic programming / recursive exhaustive / backtracking 
        from top to bottom 
        : param Coins: 
        : param AMOUNT: 
        : return: 
The results: 9 

length performed: 
( 'coinChange_1_1', .0018791932531923659) 
( 'coinChange_1_2', .10514478138982856) 
( 'coinChange_2_1', .00021833724987438408) 
( 'coinChange_2_2', .0006242205989998584)
 
Process Finished Exit with code 0


Guess you like

Origin www.cnblogs.com/wodeboke-y/p/12391282.html