1.2.2-凑零钱问题(暴力递归+动态规划)

本文详细介绍了LeetCode 322零钱兑换问题的动态规划解法,涉及状态转移方程、备忘录递归、dp数组迭代等优化策略,适合动态规划初学者掌握算法设计技巧。

Reference

LeetCode 322. 零钱兑换
labuladong的算法小抄
Markdown语法


Labuladong的算法小抄(纸质书籍 2021年1月第1版,2022年1月第七次印刷 第2章,第1节)


此问题解法和上一个斐波那契数列问题解法,我都会详细介绍解法原理,再后续动态规划算法原理和此相同,我只会解释题目解决方案窍门(即找到“状态”、“选择”和状态转移方程),不会再详细解释其他相关知识

动态规划一般解法

暴力穷举 -> 带备忘录的递归解法 -> dp 数组的迭代解法。
找到“状态”和“选择”->明确dp数组/函数的定义->寻找状态之间的关系。

难点

  • dp数组的含义
  • 寻找正确的状态转移方程(数学归纳法)

代码解释详见 Labuladong的算法小抄 书箱(2022年1月第七次印刷) pp.37-42

  先看下题⽬:给你 k 种⾯值的硬币,⾯值分别为 c1, c2 … ck,每种硬币的数量⽆限,再给⼀个总⾦额 amount ,问你最少需要⼏枚硬币凑出这个⾦额,如果不可能凑出,算法返回 -1。
算法的函数签名如下:
image
  ⽐如说k=3,⾯值分别为1,2,5,总⾦额amount=11。那么最少需要3枚硬币凑出,即11=5+5+1。
  你认为计算机应该如何解决这个问题?显然,就是把所有肯能的凑硬币⽅法都穷举出来,然后找找看最少需要多少枚硬币。
  ⾸先,这个问题是动态规划问题,因为它具有「最优⼦结构」的。要符合「最优⼦结构」,⼦问题间必须互相独⽴。啥叫相互独⽴?你肯定不想看数学证明,我⽤⼀个直观的例⼦来讲解。
  ⽐如说,你的原问题是考出最⾼的总成绩,那么你的⼦问题就是要把语⽂考到最⾼,数学考到最⾼……为了每门课考到最⾼,你要把每门课相应的选择题分数拿到最⾼,填空题分数拿到最⾼……当然,最终就是你每门课都是满分,这就是最⾼的总成绩。
  得到了正确的结果:最⾼的总成绩就是总分。因为这个过程符合最优⼦结构,“每门科⽬考到最⾼”这些⼦问题是互相独⽴,互不⼲扰的。
  但是,如果加⼀个条件:你的语⽂成绩和数学成绩会互相制约,此消彼⻓。这样的话,显然你能考到的最⾼总成绩就达不到总分了,按刚才那个思路就会得到错误的结果。因为⼦问题并不独⽴,语⽂数学成绩⽆法同时最优,所以最优⼦结构被破坏。
  回到凑零钱问题,为什么说它符合最优⼦结构呢?⽐如你想求amount=11时的最少硬币数(原问题),如果你知道凑出amount=10的最少硬币数(⼦问题),你只需要把⼦问题的答案加⼀(再选⼀枚⾯值为1的硬币)就是原问题的答案,因为硬币的数量是没有限制的,⼦问题之间没有相互制,是互相独⽴的。
  那么,既然知道了这是个动态规划问题,就要思考如何列出正确的状态转移⽅程
  先确定「状态」,也就是原问题和⼦问题中变化的变量。由于硬币数量⽆限,所以唯⼀的状态就是⽬标⾦额amount。
  然后确定 dp 函数的定义:当前的⽬标⾦额是 n ,⾄少需要dp(n)个硬币凑出该⾦额。
  然后确定「选择」并择优,也就是对于每个状态,可以做出什么选择改变当前状态。具体到这个问题,⽆论当的⽬标⾦额是多少,选择就是从⾯额列表coins 中选择⼀个硬币,然后⽬标⾦额就会减少:
  最后明确 base case,显然⽬标⾦额为 0 时,所需硬币数量为 0;当⽬标⾦额⼩于 0 时,⽆解,返回 -1:

方法1:暴力递归 (存在大量的重叠子问题)

递归问题最好都画出递归树,方法理解算法和计算时间空间复杂度
递归算法的时间复杂度:用子问题个数乘以解决一个子问题需要的时间。
  ⾄此,状态转移⽅程其实已经完成了,以上算法已经是暴⼒解法了,以上代码的数学形式就是状态转移⽅程:
image

def func():
	coins = list(map(int,input().strip().split()))
	N = int(input()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZhemgLee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值