欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Leetcode322.零钱兑换

程序员文章站 2022-07-16 09:58:13
...

Leetcode322.零钱兑换
思路:
一开始想起来的就是给现有的零钱进行排序,然后选取最大面值的零钱,进行回溯,找到就立即退出,这样的做法没有考虑到1,7,10 amount = 14这种情况,10,1,1,1,1与7,7肯定是最少两个硬币。如果说遍历所有的情况,不提前退出,会出现超时的情况。那么回溯的时候不用每次都只减一个coins[i],而是每次减个amount/coins[i]coins[i],这样的话也不行,没有考虑到2,4,5 amount= 11这种情况,因为一次性减25的话,由于找不到1,结果就是-1,其实结果应该是2,4,5,结果为3
所以这道题用dfs是需要花费些心思的,还需要进行剪枝来防止超时的发生。

class Solution {
    int min = Integer.MAX_VALUE;
    public int coinChange(int[] coins, int amount) {
        Arrays.sort(coins);
        helper(coins,amount,0,coins.length-1);
        if(min == Integer.MAX_VALUE){
            return -1;
        }else{
            return min;
        }
    }
    public void helper(int[] coins,int amount,int count,int index){
        if(amount == 0){
            min = Math.min(min,count);
            return;
        }
        if(index < 0) return;
        for(int k = amount/coins[index];k >= 0 && k + count < min;k--){//剪枝条件
                helper(coins,amount-k*coins[index],count+k,index-1);
            }
    }
}

第二种做法就是使用动态规划方法
f(i)为为实现为i的钱数需要多少硬币,总共的硬币面额为2,3,4
f(1) = min(f(1-2),f(1-3),f(1-4))+1;
f(2)= min(f(2-2),f(2-3),f(2-4))+1;
f(3)=min(f(3-2),f(3-3),f(3-4))+1;
.
.
.
f(i) = min(f(i-2),f(i-3),f(i-4))+1;

class Solution {
    int min = Integer.MAX_VALUE;
    public int coinChange(int[] coins, int amount) {
       // Arrays.sort(coins);
        int[] dp = new int[amount+1];
        Arrays.fill(dp,amount+1);
        dp[0] = 0;
        for(int i = 1;i <= amount;i++){
            for(int j = 0;j < coins.length;j++){
                if(i >= coins[j]){
                    dp[i] = Math.min(dp[i],dp[i-coins[j]]+1);
                }  
            }
        }
        return dp[amount] == amount+1? -1:dp[amount];
    }

}