zoukankan      html  css  js  c++  java
  • leetcode hot 100-17. *的字母组合

    322. 零钱兑换

    给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。

    你可以认为每种硬币的数量是无限的。

    示例 1:

    输入:coins = [1, 2, 5], amount = 11
    输出:3 
    解释:11 = 5 + 5 + 1

    示例 2:

    输入:coins = [2], amount = 3
    输出:-1

    示例 3:

    输入:coins = [1], amount = 0
    输出:0

    示例 4:

    输入:coins = [1], amount = 1
    输出:1

    示例 5:

    输入:coins = [1], amount = 2
    输出:2

    提示:

    1 <= coins.length <= 12
    1 <= coins[i] <= 231 - 1
    0 <= amount <= 104

    思路一:回溯

    回溯,每次可以继续选当前面值的硬币,也可以选下个面值的硬币
     1 class Solution {
     2     public int count = 1 << 30;
     3     public boolean flag = false;
     4 
     5     public int coinChange(int[] coins, int amount) {
     6         // 先对coins进行大小排序
     7         Arrays.sort(coins);
     8         traceBack(coins, coins.length-1, 0, amount, 0);
     9         return flag ? count : -1;
    10     }
    11 
    12     // 回溯,每次可以继续选当前面值的硬币,也可以选下个面值的硬币
    13     public void traceBack(int[] coins, int nowIndex, int nowSum, int amount, int cnt){
    14 
    15         if(nowIndex < 0){
    16             return;
    17         }
    18         if(nowSum >= amount){
    19             if(nowSum == amount){
    20                 count = Math.min(count, cnt);
    21                 flag = true;
    22             }
    23             return;
    24         }
    25         if(nowSum + coins[nowIndex] <= amount){
    26             traceBack(coins, nowIndex, nowSum + coins[nowIndex], amount, cnt + 1);
    27         }
    28             traceBack(coins, nowIndex - 1, nowSum , amount, cnt);
    29     }
    30 }

    时间超时

    复杂度分析:

    思路二:完全背包的动态规划

    参考:https://leetcode-cn.com/problems/coin-change/solution/322-ling-qian-dui-huan-by-leetcode-solution/

    dp[i][j]表示使用前i中面值的硬币能构成总金额为j的最少硬币个数
    当选当前面值的硬币是dp[i][j] = dp[i-1][j-coins[i]];
    当不选是d[i][j] = d[i][j];
    所以状态转移方程为 dp[i][j] = Math.min(dp[i-1][j], dp[i][j-coins[i]] + 1);
    初值,dp[i][0] = 0,凑成总金额为0需要的最少硬币个数始终为0
    不降维的代码,一直有问题,但是不知道哪里错了
     1 class Solution {
     2     public int coinChange(int[] coins, int amount) {
     3         int len = coins.length;
     4         int[][] dp = new int[len + 1][amount + 1];
     5         int inf = 1 << 30;
     6         for(int i = 0; i <= len; i++){
     7             Arrays.fill(dp[i], inf);
     8             dp[i][0] = 0;
     9         }
    10 
    11         for(int i = 1; i <= len; i++){
    12             for(int j = coins[i-1]; j <= amount; j++){
    13                 dp[i][j] = Math.min(dp[i-1][j], dp[i][j - coins[i - 1]] + 1);
    14             }
    15         }
    16         return dp[len][amount] == inf ? -1 : dp[len][amount];
    17     }
    18 }

    空间降维后的代码可以通过

     1 class Solution {
     2     public int coinChange(int[] coins, int amount) {
     3 
     4         int len = coins.length;
     5         int[] dp = new int[amount + 1];
     6         int inf = 1 << 30;
     7         Arrays.fill(dp, inf);
     8         dp[0] = 0;
     9         for(int i = 1; i <= len; i++){
    10             for(int j = coins[i-1]; j <= amount; j++){
    11                 dp[j] = Math.min(dp[j], dp[j - coins[i - 1]] + 1);
    12             }
    13         }
    14         return dp[amount] == inf ? -1 : dp[amount];
    15     }
    16 }
    leetcode 执行用时:13 ms > 91.36%, 内存消耗:38.1 MB > 84.41%

    复杂度分析:

    时间复杂度:O(nc)。两个循环,所以时间复杂度为O(nc)。c是 amount。
    空间复杂度:O(c)。只需要一个 大小为 acmount的数组。
  • 相关阅读:
    1052 Linked List Sorting (25 分)
    1051 Pop Sequence (25 分)
    1050 String Subtraction (20 分)
    1049 Counting Ones (30 分)
    1048 Find Coins (25 分)
    1047 Student List for Course (25 分)
    1046 Shortest Distance (20 分)
    1045 Favorite Color Stripe (30 分)
    1044 Shopping in Mars (25 分)
    1055 The World's Richest (25 分)
  • 原文地址:https://www.cnblogs.com/hi3254014978/p/13899283.html
Copyright © 2011-2022 走看看