zoukankan      html  css  js  c++  java
  • 322.零钱兑换(动态规划和贪心)

    322. 零钱兑换#

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

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/coin-change
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    基本是按照这篇题解的思路

    贪心
    11. 想要总硬币数最少,肯定是优先用大面值硬币,所以对 coins 按从大到小排序
    12. 先丢大硬币,再丢会超过总额时,就可以递归下一层丢的是稍小面值的硬币

    乘法对加法的加速
    21. 优先丢大硬币进去尝试,也没必要一个一个丢,可以用乘法算一下最多能丢几个

    k = amount / coins[c_index] 计算最大能投几个
    amount - k * coins[c_index] 减去扔了 k 个硬币
    count + k 加 k 个硬币
    
    如果因为丢多了导致最后无法凑出总额,再回溯减少大硬币数量
    

    最先找到的并不是最优解
    31. 注意不是现实中发行的硬币,面值组合规划合理,会有奇葩情况
    32. 考虑到有 [1,7,10] 这种用例,按照贪心思路 10 + 1 + 1 + 1 + 1 会比 7 + 7 更早找到
    33. 所以还是需要把所有情况都递归完

    ans 疯狂剪枝
    41. 贪心虽然得不到最优解,但也不是没用的
    42. 我们快速算出一个贪心的 ans 之后,虽然还会有奇葩情况,但是绝大部分普通情况就可以疯狂剪枝了

    作者:ikaruga
    链接:https://leetcode-cn.com/problems/coin-change/solution/322-by-ikaruga/
    来源:力扣(LeetCode)
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    class Solution {
        private int min=Integer.MAX_VALUE;
        public int coinChange(int[] coins, int amount) {
            if(coins==null||coins.length==0)
                return -1;
            Arrays.sort(coins);
            helper(coins,0,coins.length-1,amount);
            return min==Integer.MAX_VALUE?-1:min;
        }
        public void helper(int[] coins,int res,int index,int all)
        {
            if(all==0)
            {
                min=Math.min(res,min);
                return ;
            }
            if(index<0) //说明这种移动不能得到一个有效值,所以直接返回。
                return;
            for(int i=all/coins[index];i>=0&&res+i<min;i--) //这里i取到0就会跳到下一个位置,就可以在最上层实现移动。
            {
                helper(coins,res+i,index-1,all-i*coins[index]);
            }
        }
    }
    

    使用dp来做,让amount从小到大增加,使得后面的dp值复用前面的

    class Solution {
        public int coinChange(int[] coins, int amount) {
            if(coins==null||coins.length==0)
                return -1;
           int[] dp=new int[amount+1];
           for(int i=1;i<dp.length;i++)
                dp[i]=Integer.MAX_VALUE;
           for(int i=1;i<=amount;i++)
           {
               int min=Integer.MAX_VALUE;
               for(int j=0;j<coins.length;j++)
               {
                   if(i-coins[j]>=0&&(dp[i-coins[j]]!=Integer.MAX_VALUE))
                        min=Math.min(dp[i-coins[j]]+1,min);
               } 
               dp[i]=min; 
           }
    
           return dp[amount]==Integer.MAX_VALUE?-1:dp[amount];
        }
     
    }
    
  • 相关阅读:
    【今日CS 视觉论文速览】4 Jan 2019
    【今日CS 视觉论文速览】3 Jan 2019
    【今日CS 视觉论文速览】1 Jan 2019
    【机器学习】混淆矩阵及其绘制
    【Vim】批量插入注释符号
    【今日CS 视觉论文速览】31 Dec 2018
    【深度学习风格化/生成艺术】图像融合--毫无违和
    CSDN的一些年度大牛(2018)
    【今日CS 视觉论文速览】 27 Dec 2018
    python与机器视觉(X)打包为exe可执行文件
  • 原文地址:https://www.cnblogs.com/cold-windy/p/12444427.html
Copyright © 2011-2022 走看看