【贪心算法】:LeetCode860.柠檬水找零

朋友们、伙计们,我们又见面了,本专栏是关于各种算法的解析,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成!

C 语 言 专 栏:C语言:从入门到精通

数据结构专栏:数据结构

个  人  主  页 :stackY、

C + + 专 栏   :C++

Linux 专 栏  :Linux

目录

1. 题目解析

2. 算法原理讲解

3. 代码实现

4. 贪心策略证明


1. 题目解析

LeetCode860.柠檬水找零:https://leetcode.cn/problems/lemonade-change/description/icon-default.png?t=N7T8https://leetcode.cn/problems/lemonade-change/description/

860. 柠檬水找零

在柠檬水摊上,每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。

每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。

注意,一开始你手头没有任何零钱。

给你一个整数数组 bills ,其中 bills[i] 是第 i 位顾客付的账。如果你能给每位顾客正确找零,返回 true ,否则返回 false 。

示例 1:

输入:bills = [5,5,5,10,20]
输出:true
解释:
前 3 位顾客那里,我们按顺序收取 3 张 5 美元的钞票。
第 4 位顾客那里,我们收取一张 10 美元的钞票,并返还 5 美元。
第 5 位顾客那里,我们找还一张 10 美元的钞票和一张 5 美元的钞票。
由于所有客户都得到了正确的找零,所以我们输出 true。

示例 2:

输入:bills = [5,5,10,10,20]
输出:false
解释:
前 2 位顾客那里,我们按顺序收取 2 张 5 美元的钞票。
对于接下来的 2 位顾客,我们收取一张 10 美元的钞票,然后返还 5 美元。
对于最后一位顾客,我们无法退回 15 美元,因为我们现在只有两张 10 美元的钞票。
由于不是每位顾客都得到了正确的找零,所以答案是 false。

提示:

  • 1 <= bills.length <= 105
  • bills[i] 不是 5 就是 10 或是 20 

根据题意:首先找零是按照顺序来进行的,不能“插队”,并且刚开始我们身无分文。

假设第一个顾客给5块,那么直接收下即可;

如果第一个顾客给的不是5块,那表示需要给顾客找零,但是此时我们没有钱,所以直接返回false即可。 

2. 算法原理讲解

首先:我们根据顾客支付的钱可以分为三种情况:

1. 顾客支付5元 -> 直接收下即可;

2. 顾客支付10元 -> 直接收下,并且判断身上是否有5元,如果有找零给顾客,如果没有直接返回false;

3. 顾客支付20元 -> 直接收下,此时给顾客找零就存在两种方法:

        ① 找给顾客一张10元和一张5元;

        ② 找给顾客三张5元;

那么该如何选择上述两种情况呢?

就需要用到贪心算法,那么到底该怎么贪才是最优呢?

上面的两种方法其本质上就是一张10元与两张5元的区别,那么根据贪心策略该怎么贪呢?

仔细观察不难发现,5元的用处是很大的,不仅可以给10元找零,还可以给20元找零,那么既然5元用处这么大,就表示5元比较珍贵,所以越珍贵的东西我们越舍不得用,所以尽量选择找零5元比较少的那一个方法,所以我们的贪心策略是:尽可能少的使用5元钱给顾客找零。

3. 代码实现

怎么记录我们手上的钱呢?

可以使用两个变量来统计此时我们手中所具有的5元钱的张数(cnt_five)和10元钱cnt_ten),然后遍历bills,遇到5元将cnt_five++,遇到10元钱先看自己手里有没有钱,遇到20元首先考虑的就是10+5的策略,再考虑5+5+5的策略。

class Solution 
{
public:bool lemonadeChange(vector<int>& bills) {//统计5元钱和10元钱的张数int cnt_ten = 0, cnt_five = 0; //遍历for(auto& e : bills){if(e == 5) cnt_five++;   //遇到5元就收下else if(e == 10)         //遇到10元{cnt_ten++;if(cnt_five) cnt_five--; //先判断是否可以找零else return false;}else                     //遇到20元{if(cnt_five && cnt_ten) //先考虑10+5的策略{cnt_five--;cnt_ten--;}else if(cnt_five >= 3) cnt_five -= 3; //再考虑5+5+5的策略else return false;}}//走到这里就说明找零成功return true;}
};

4. 贪心策略证明

那么如果证明我们选择的这种贪心策略是否正确呢?

需要用到:交换论证法

例如:

假设贪心解为 [a, b, c, d, e, f]

假设最优解为 [e, b, c, d, a, f]

交换论证就是在不破坏最优解的“最优性质”的前提下可以通过一定的调整将最优解转化为贪心解即可

将最优解里面的e和a交换,这样既没有破坏最优解性质,同样也可以将最优解转化为贪心解,则表示该贪心策略正确。

在本题中使用交换论证法:遇到顾客给20元,贪心解是用10元和5元进行找零,最优解是用三张5元进行找零,区别就在于两张5元和一张10元。

顾客         ...  5   10   20        10  ...

贪心解     ...  0    5   10+5      5  ...

最优解     ...  0    5    5+5+5   5  ...

那么在整个找零过程中,最优解的10元存在花与不花两种情况:

① 如果在前面或者后面的找零过程中,将10元钱花了,那么在后面花的10元钱可以将这里的5+5给替换掉,此时也就变成了贪心解;

② 如果在前面或者后面的找零过程中,没有将10钱花掉,那么就可以用没花掉的10元钱替换掉这里的5+5,此时也变成了贪心解。

所以通过交换论证法证明了最优解可以在不改变最优条件的性质下变成贪心解,所以证明我们的贪心策略(选择花费5元较少的一种方法)是正确的。

朋友们、伙计们,美好的时光总是短暂的,我们本期的的分享就到此结束,欲知后事如何,请听下回分解~,最后看完别忘了留下你们弥足珍贵的三连喔,感谢大家的支持!      

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/488650.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

类型转换(C++)

一、C语言中的类型转换 在C语言中&#xff0c;如果赋值运算符左右两侧类型不同&#xff0c;或者形参与实参类型不匹配&#xff0c;或者返回值类型与 接收返回值类型不一致时&#xff0c;就需要发生类型转化&#xff0c;C语言中总共有两种形式的类型转换&#xff1a;隐式类型 …

Linux-用户和权限(黑马学习笔记)

认识root用户 root用户&#xff08;超级管理员&#xff09; 无论是Windows、MacOS、Linux均采用多用户的管理模式进行权限管理。 ● 在Linux系统中&#xff0c;拥有最大权限的账户名为&#xff1a;root&#xff08;超级管理员&#xff09; ● 而在前期&#xff0c;我们一直…

YApi-pro docker安装在centos7上

之前安装失败了&#xff0c;只好在docker中装了。 准备环境 1.docker安装 centos7 docker 安装-CSDN博客 2.mongodb数据库docker安装 创建mongo容器目录 mkdir /data/mongo -p docker pull mongo:4.2.21 创建一个yapi网络插件 docker network create yapi …

FFmpeg解析之avformat_find_stream_info函数

avformat_find_stream_info 的主要作用就是&#xff1a;解析媒体文件并获取相关的流信息 整体的逻辑如下图所示&#xff1a; /*** Read packets of a media file to get stream information. This* is useful for file formats with no headers such as MPEG. This* function…

关于Kinect 互动沙盘 深度图 Shader Graph 分层

把Kinect的深度图穿给Shader Graph using com.rfilkov.kinect; using UnityEngine; using UnityEngine.UI; public class GetDepthTex : MonoBehaviour { public Material Mat_SandTable; void Update() { Mat_SandTable.SetTexture("_MainTex"…

MongoDB实战 – 用Python访问MongoDB数据库

MongoDB实战 – 用Python访问MongoDB数据库 MongoDB in Action – Access MongoDB Databases with Python By JacksonML Python语言功能强大众所周知&#xff0c;在数据库管理领域也无所不能。MongoDB是文档数据库&#xff0c;属于NoSQL数据库的一种&#xff0c;在业界也非常…

javaEE图书馆自习室订座系统信用springmvc+springboot+mybatis

研究的内容是设计和实现图书馆自习室系统&#xff0c;便捷广大师生对自习室的使用&#xff0c;协助图书馆自习室管理。在设计过程中&#xff0c;系统的用户角色和权限分配如下&#xff1a; &#xff08;1&#xff09;馆长 用户管理&#xff1a;拥有自习室管理员、普通用户的所有…

LiveQing视频点播流媒体RTMP推流服务功能-支持配置开启 HTTPS 服务什么时候需要开启HTTPS服务

LiveQing视频点播流媒体RTMP推流服务功能支持配置开启 HTTPS 服务什么时候需要开启HTTPS服务 1、配置开启HTTPS1.1、准备https证书1.1.1、选择Nginx类型证书下载 1.2、配置 开启 HTTPS1.2.1 web页面配置1.2.2 配置文件配置 2、验证HTTPS服务3、为什么要开启HTTPS3.1、安全性要求…

访问raw.githubusercontent.com失败问题的处理

1 问题 GitHub上的项目的有些资源是放在raw.githubusercontent.com上的&#xff0c;通常我们在安装某些软件的时候会从该地址下载资源&#xff0c;直接访问的话经常容易失败。 # 安装operator kubectl apply -f https://raw.githubusercontent.com/oceanbase/ob-operator/2.1…

Element Plus 的下拉选择器el-option的字体全部蓝色,全部是选中状态

问题 原因 参考官方&#xff1a; Select 选择器 | Element Plus 解决方案1&#xff1a; 给外层el-select增加一个value-key指定值: value-key"ID" <el-select value-key"ID"ref"productName"v-model"selectedProduct.GOODS_DESC"…

uni-app 经验分享,从入门到离职(五)——由浅入深 uni-app 数据缓存

文章目录 &#x1f4cb;前言⏬关于专栏 &#x1f3af;什么是数据存储&#x1f9e9;数据存储——存储&#x1f4cc; uni.setStorage(OBJECT)&#x1f4cc; uni.setStorageSync(KEY,DATA) &#x1f9e9;数据存储——获取&#x1f4cc; uni.getStorage(OBJECT)&#x1f4cc; uni.g…

​​​​​​​Sora:OpenAI的革命性AI视频模型与其对未来影像创作的影响

随着深度学习技术和计算能力的进步&#xff0c;人工智能不仅在图像识别、自然语言处理等领域取得了卓越成就&#xff0c;同时也在不断突破视频处理和生成的边界。在这一背景下&#xff0c;OpenAI推出了Sora——一种新型的AI视频模型&#xff0c;标志着AI在视频内容创作领域的又…