01 | 硬币找零问题:从贪心算法说起

作为“初识动态规划”模块的第一节课,我会带着你一起从贪心算法开始了解整个知识体系的脉络。现实中,我们往往不愿意承认自己贪婪。事实上,贪婪是渴望而不知满足,它是人的一种基本驱动力。既然是基本驱动力,那它自然就不会太难。

所以你可能会说贪心算法很简单啊,但其实不然,这里面还真有不少门道值得我们说说。而且,它还跟动态规划问题有着千丝万缕的联系,能够帮助我们理解真正的动归问题。

接下来我们就从一个简单的算法问题开始探讨,那就是硬币找零。在开始前,先提出一个问题:任何算法都有它的局限性,贪心算法也如此,那么贪心算法能解决哪些问题呢?

不妨带着这个问题来学习下面的内容。

硬币找零问题

移动支付已经成为了我们日常生活当中的主流支付方式,无论是在便利店购买一瓶水,还是在超市或菜市场购买瓜果蔬菜等生活用品,无处不在的二维码让我们的支付操作变得异常便捷。

但在移动支付成为主流支付方式之前,我们常常需要面对一个简单问题,就是找零的问题。

虽然说硬币找零在日常生活中越来越少,但它仍然活跃在编程领域和面试问题当中,主要还是因为它极具代表性,也能多方面考察一个开发人员或面试者解决问题的能力。

既然如此,我们就先来看看这个算法问题的具体描述。

问题:给定 n 种不同面值的硬币,分别记为 c[0], c[1], c[2], … c[n],同时还有一个总金额 k,编写一个函数计算出最少需要几枚硬币凑出这个金额 k?每种硬币的个数不限,且如果没有任何一种硬币组合能组成总金额时,返回 -1。

示例 1:

输入:c[0]=1, c[1]=2, c[2]=5, k=12
输出:3 
解释:12 = 5 + 5 + 2
示例 2:

输入:c[0]=5, k=7
输出:-1
解释:只有一种面值为5的硬币,怎么都无法凑出总价值为7的零钱。

题目中有一个醒目的提示词,那就是“最少”。嗯,看起来这是一个求最值的问题,其实也好理解,如果题目不在这里设定这一条件,那么所求结果就不唯一了。

举个简单的例子,按照示例 1 的题设,有三种不同面值的硬币,分别为 c1=1, c2=2, c3=5,在没有“最少”这一前提条件下你能罗列出几种不同的答案?我在这里随意列出几个:

解1:输出:5,因为 5 + 2 + 2 + 2 + 1 = 12。
解2:输出:6,因为 2 + 2 + 2 + 2 + 2 + 2 = 12。
解3:输出:12,因为 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 = 12。

所以,这是一个求最值的问题。那么求最值的核心问题是什么呢?嗯,无非就是穷举,显然,就是把所有可能的凑硬币方法都穷举出来,然后找找看最少需要多少枚硬币,那么最少的凑法,就是这道题目的答案。

在面试中,一般来说穷举从来都不是一个好方法。除非你要的结果就是所有的不同组合,而不是一个最值。但即便是求所有的不同组合,在计算的过程中也仍然会出现重复计算的问题,我们将这种现象称之为重叠子问题

请你记住这个关键概念,它是动态规划当中的一个重要概念。但现在你只需要知道所谓重叠子问题就是:我们在罗列所有可能答案的过程中,可能存在重

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值