Java实现如下:

public class Solution {
    public int coinChange(int[] coins, int amount) {
        if (amount == 0) return 0;
        int[] dp = new int[amount + 1];
        dp[0] = 0;
        for (int i = 1;i <= amount ;i++ ) {
            dp[i] = Integer.MAX_VALUE;
            for(int k :coins) {
                if(i>=k && dp[i-k] != Integer.MAX_VALUE) {
                    dp[i] = Math.min(dp[i-k] + 1,dp[i]);
                }
            }
        }
        if(dp[amount]<Integer.MAX_VALUE && dp[amount] > 0) {
            return dp[amount];
        } else {
            return -1;
        }

    }
}

 

Java第二种实现:

 1 class Solution {
 2     public int coinChange(int[] coins, int amount) {
 3         int[] dp = new int[amount+1];
 4         dp[0] = 0;
 5         for(int i=1;i<amount+1;i++){
 6             dp[i] = amount + 1;
 7         }
 8 
 9         for(int i=1;i<amount+1;i++){
10             int minNumber = amount + 1;
11             for(int coin : coins){
12                 int preIndex = i-coin;
13                 if(preIndex<0){
14                     continue;
15                 }else{
16                     minNumber = Math.min(minNumber,dp[preIndex]);
17                 }                
18             }
19             dp[i] = minNumber + 1;
20         }
21         return dp[amount] >= amount + 1 ? -1 : dp[amount];
22     }
23 }

 

补充一个python的实现:

 1 import sys
 2 class Solution:
 3     def coinChange(self, coins: 'List[int]', amount: int) -> int:
 4         dp = [sys.maxsize for i in range(amount+1)]
 5         dp[0] = 0
 6         for i in range(1,amount+1):
 7             for k in coins:
 8                 if i >= k and dp[i-k] != sys.maxsize:
 9                     dp[i] = min(dp[i],dp[i-k]+1)
10                         
11         return -1 if dp[amount] == sys.maxsize else dp[amount]

注意内层循环范围是coins,而不要使用range(amount+1),否则会TLE。DP方案执行时间:1700ms。

 

补充另一种解法,BFS + memo,效率要高一些,执行时间:1000ms。

 1 class Solution:
 2     def coinChange(self, coins: 'List[int]', amount: int) -> int:
 3         n = len(coins)
 4         if amount == 0:
 5             return 0
 6         target = {amount}
 7         memo = set()
 8         level = 0
 9         result = amount + 1
10         while target:
11             cur = set()
12             for t in target:
13                 if t not in memo:
14                     memo.add(t)
15                     for c in coins:
16                         if t - c == 0:
17                             result = min(result,level + 1)
18                             #return level + 1
19                         if t - c > 0:
20                             cur.add(t - c)
21             target = cur
22             level += 1
23         return -1 if result > amount else result

思路,使用memo记录已经“扩展”的节点,之后再遇到同样数值的节点,就不再扩展了(二叉树剪枝)。

target中存储当前层的节点,cur记录下一层的节点。

注意第16行,t - c == 0时,说明发现一种可以满足要求的方案,此时记录当前树的高度,并更新result。result中保存全局最小的满足条件的树的高度值。

posted on 2018-10-14 20:03  Sempron2800+  阅读(207)  评论(0编辑  收藏  举报