leetcode 322. Coin Change

来源:互联网 发布:剑三大师捏脸数据 编辑:程序博客网 时间:2024/06/06 01:51
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.Example 1:coins = [1, 2, 5], amount = 11return 3 (11 = 5 + 5 + 1)Example 2:coins = [2], amount = 3return -1.Note:You may assume that you have an infinite number of each kind of coin.

给出两种解法
第一种解法会超时
主要是dp[i][j] 表示用前i种硬币,生成j

    public int coinChange_bad(int[] coins, int amount) {        if(coins==null || coins.length==0) return -1;        int[][] dp = new int[coins.length+1][amount+1];        int t,k;        Arrays.fill(dp[0], -1);        for(int i=0; i< coins.length; i++)            dp[i][0] = 0;        for(int i=1; i < coins.length +1; i++){            // Arrays.fill(dp[i], -1);            for(int j=1; j < amount+1; j++){                dp[i][j] = dp[i-1][j] >0 ? dp[i-1][j] : Integer.MAX_VALUE;                t = j - coins[i-1];                k=1;                while(t>=0 ){                    if(dp[i][t] >= 0)                        dp[i][j] = Math.min(dp[i][j], dp[i][t] + k);                    t -= coins[i-1];                    k++;                }                if(dp[i][j] == Integer.MAX_VALUE)                     dp[i][j] = -1;            }        }        // for(int i=0; i< coins.length+1; i++)        //     System.out.println(Arrays.toString(dp[i]));        return dp[coins.length][amount];    }

第二种解法,终于AC了
主要是减少无谓的判断
dp[i]表示用coins集合组合成i的最少个数,不能为-1.
所以只需判断
dp[i- k*coins[j]]就可以,取最小,k从小到大,能找到,就停止。

    public int coinChange(int[] coins, int amount) {        if(coins==null || coins.length==0) return -1;        int[] dp = new int[amount+1];        Arrays.fill(dp, -1);        dp[0] = 0;        Arrays.sort(coins);        for(int i=0; i<coins.length; i++){            if(coins[i] < amount){                dp[coins[i]] = 1;            }else{                break;            }        }        for(int j = 1; j < amount+1; j++){            if(dp[j] > 0 || j < coins[0]) continue;            int min = Integer.MAX_VALUE;            int k=1;            while(j - coins[0]*k >=0 ){                min = Integer.MAX_VALUE;                for(int i=0; i< coins.length; i++){                    int t = j-k*coins[i];                    if(t < 0) break;                    if(dp[t] >= 0){                        min = Math.min(min, dp[t]+k);                    }                }                if(min < Integer.MAX_VALUE)                    break;                k++;            }            if(j - coins[0]*k <0 )                dp[j] = -1;            else                dp[j] = min;        }        return dp[amount];    }