硬币问题 动态规划_动态规划

硬币问题 动态规划_动态规划动态规划-硬币问题分析

大家好,又见面了,我是你们的朋友全栈君。

什么是动态规划

上次对动态规划已经有了个大概的分析。引用维基百科的话就是:
dynamic programming is a method for solving a complex problem by breaking it down into a collection of simpler subproblems

翻译过来就是动态规划就是通过拆分问题,来解决复杂的问题的一个方式。所以我们也知道,动态规划的核心就是如何取拆分这个问题那如何拆分问题,这个也就成为我们要去研究的重点。借鉴于大部分权威人士比较认同的观点是:拆分问题,靠的是状态的定义和状态转移方程的定义。
这里有一遍知乎是对上面的定义的见解:www.zhihu.com/question/23…

什么是状态的定义

我们对状态的定义是这样的:解答动态规划问题,需要开一个数组,数组中的每一个元素f[i]或f[i][j]代表了什么。而状态的定义需要两个步骤:
1.最后一步;
2.子问题。

题目描述

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 Given coins = [1, 2, 5], amount = 11 return 3 (11 = 5 + 5 + 1)

Given coins = [2], amount = 3 return -1.

Notice You may assume that you have an infinite number of each kind of coin.

问题简单解释:现有不同币值的硬币,凑足一个给定的金额,不能多不能少,得出最少的硬币个数;如果无解,返回-1。

解题思路

那我们重新返回之前说的状态的定义的两个步骤。
最后一步:

我们就从例子里面说的,有1,2,5三个币值的硬币,凑足11块。我们假设最优策略是k个硬币凑足了11块,最后的一块硬币币值是a(K)元,则前面的硬币拼出的币值为11-a(K)元,这就是先着手最后一步的状态定义。
然后从子问题讲:
由于我们已经从最后一步定义,将原问题转化成另外一个问题是用最少的硬币凑足11-a(K)元,此时将原规模变小,而此时的问题就是原问题的子问题。可以将凑足多少元(即规模)定义为X,则可以用状态f(X) = 用最少的硬币凑足X元。我们假设最后一枚硬币是1,则f(11) = f(11 -1)+1枚;最后一枚是2,则f(11) = f(11-2)+1枚;同理,最后一枚为5,则f(11)=f(11-5)+1枚,即其实最少的硬币为f(11)=min{f(11-1)+1,f(11-2)+1,f(11-5)+1}。 我们可以用程序进行表示:

// 递归解法 
// 没有考虑边界问题
伪代码
int f(x){
if(x==0)return 0;
int res = Integer.MAX_VALUE;
if(x>=1){
res = Math.min(f(x-1)+1,res);
}
if(x>=2){
res = Math.min(f(x-2)+1,res);
}
if(x>=5){
res = Math.min(f(x-5)+1,res);
}
return res;
}
复制代码

但递归法解法做了很多重复计算,比如f(9)->f(11-1)->f(10-9)或者f(11-2)计算可得。这时候我们可以从动态规划第二部分—状态的转移。

其实很简单将f(x) 变成一个数组f[x],将计算结果保存起来。此时函数f[x]=min{f[x-1]+1,f[x-2]+1,f[x-5]+1}。
由于是个数组,所以我们应该考虑下边界和初始值的问题。假设拼不出来的值如f[-1]或者f[-3]这种,我们定义为正无穷Max_Value,初始值f[0]=0代表要拼出0元即为0个硬币。此时我们应当从小到大顺序算出每个元素的最小硬币值,即:
f[1]=min{f[1-1]+1,f[1-2]+1,f[1-5]+1}=f[0]+1 = 1

f[2] = min{f[2-1]+1,f[2-2]+1,f[2-5]+1} = f[0]+1 = 1,

我们不难发现,当f[2]以1块为最后的硬币时,f[1]其实已经保存该值的最小硬币数,不会重复计算,且算法时间度是X*3

可以看下程序:

public int coinChange(int[] a, int M) {
        // write your code here
        int length = a.length;
        int []f = new int[M+1];

        // 初始化
        f[0]=0;
        for(int i=1;i<=M;i++){
            // 先将f[i]初始无穷大,进行对比
            f[i]= Integer.MAX_VALUE;
            for (int j=0;j<length;j++){
                // 凑足的金额一定得大于硬币的值且减了硬币不应该等于无穷大
                if(i>=a[j]&&f[i-a[j]]!=Integer.MAX_VALUE&&f[i-a[j]]+1<f[i]){
                    f[i]= f[i-a[j]]+1;
                }
            }
        }
        if(f[M]==Integer.MAX_VALUE){
            return -1;
        }else {
            return f[M];
        }
    }
复制代码

作者简介

考拉后端开发小哥Rowland,热爱运动还有点萌!

转载于:https://juejin.im/post/5ce7d44351882530810dfd1d

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/106808.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • sql注入攻击属于什么攻击_ssr怎么用

    sql注入攻击属于什么攻击_ssr怎么用学好网络安全,以己之矛护己之盾

    2022年8月16日
    5
  • 手把手教你写专利申请书/如何申请专利

    手把手教你写专利申请书/如何申请专利手把手教你写专利申请书·如何申请专利 摘要小前言(一)申请前的准备工作   1、申请前查询   2、其他方面的考虑   3、申请文件准备(二)填写专利申请系列文档   1、实际操作步骤   2、具体操作   3、经验分享、注意事项(三)关于费用(四)其他的话参考资源提示常见问题的问与答 摘要:   如何写好专利申请?由于很多专利申请人都…

    2022年6月11日
    28
  • opencv中的cvCircle函数

    opencv中的cvCircle函数定义voidcvCircle(CvArr*img,CvPointcenter,intradius,CvScalarcolor,intthickness=1,intline_type=8,intshift=0);[1]参数img 图像center 圆心坐标radius 圆形的半径color 线条的颜色thic

    2022年7月24日
    14
  • mybatis和mybatisPlus中解决实体类字段与数据库关键字冲突问题

    mybatis和mybatisPlus中解决实体类字段与数据库关键字冲突问题

    2020年11月9日
    326
  • ubuntu18安装yarn、安装vue

    ubuntu18安装yarn、安装vue操作系统为ubuntu18第一步:换源sudopython-c"s=’mirrors.163.com’;importre;f=open(‘/etc/apt/sources.list’,’r+’);a=f.read();f.seek(0);f.truncate();f.write(re.sub(r'(deb|security)\.debian\.org’,s,a));f.clo…

    2022年5月25日
    38
  • 分辨率,像素,像素密度易懂

    分辨率,像素,像素密度易懂分辨率是什么?一般会说这个屏幕的分辨率是1920*1080,这就说明纵向和横向上有1920个和1080个像素点;像素点是什么?一个像素点就是一个色彩块,没有实际的物理尺寸;什么是屏幕像素密度?一英寸长的一条线上理论上会有多少个像素点;例如:一个手机长边有1920个像素点,短边有1080个像素点,屏幕大小(对角线的物理大小)是5.2英寸的,那么屏幕密度是怎么计…

    2022年5月4日
    60

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号