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

这篇具有很好参考价值的文章主要介绍了【贪心算法】:LeetCode860.柠檬水找零。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

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

数据结构专栏:数据结构

个  人  主  页 :stackY、

C + + 专 栏   :C++

Linux 专 栏  :Linux

【贪心算法】:LeetCode860.柠檬水找零,初阶算法,c++,开发语言

目录

1. 题目解析

2. 算法原理讲解

3. 代码实现

4. 贪心策略证明


1. 题目解析

LeetCode860.柠檬水找零:https://leetcode.cn/problems/lemonade-change/description/https://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元钱给顾客找零。

【贪心算法】:LeetCode860.柠檬水找零,初阶算法,c++,开发语言

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交换,这样既没有破坏最优解性质,同样也可以将最优解转化为贪心解,则表示该贪心策略正确。

【贪心算法】:LeetCode860.柠檬水找零,初阶算法,c++,开发语言

在本题中使用交换论证法:遇到顾客给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元较少的一种方法)是正确的。

朋友们、伙计们,美好的时光总是短暂的,我们本期的的分享就到此结束,欲知后事如何,请听下回分解~,最后看完别忘了留下你们弥足珍贵的三连喔,感谢大家的支持!      文章来源地址https://www.toymoban.com/news/detail-833222.html

到了这里,关于【贪心算法】:LeetCode860.柠檬水找零的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 贪心算法在找零问题中的应用

    找零问题是一个经典的优化问题,其目标是用最少的硬币找零给定的金额。贪心算法是解决这类问题的一种常用方法,其核心思想是在每一步选择中都采取最好或最优(即最有利)的选择,从而希望能够导致全局的最好或最优的解。在找零问题中,贪心算法的策略通常是根据

    2024年04月23日
    浏览(24)
  • 算法沉淀——贪心算法一(leetcode真题剖析)

    贪心算法(Greedy Algorithm)是一种基于贪心策略的优化算法,它通常用于求解最优化问题,每一步都选择当前状态下的最优解,以期望通过局部最优的选择最终达到全局最优。贪心算法的思想是在每一步都做出在当前状态下局部最优的选择,而不考虑未来可能造成的影响。 在

    2024年03月08日
    浏览(40)
  • 算法沉淀——贪心算法五(leetcode真题剖析)

    题目链接:https://leetcode.cn/problems/jump-game-ii/ 给定一个长度为 n 的 0 索引 整数数组 nums 。初始位置为 nums[0] 。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i + j] 处: 0 = j = nums[i] i + j n 返回到达 nums[n - 1] 的最小跳跃次

    2024年04月11日
    浏览(43)
  • 算法沉淀——贪心算法七(leetcode真题剖析)

    题目链接:https://leetcode.cn/problems/integer-replacement/ 给定一个正整数 n ,你可以做如下操作: 如果 n 是偶数,则用 n / 2 替换 n 。 如果 n 是奇数,则可以用 n + 1 或 n - 1 替换 n 。 返回 n 变为 1 所需的 最小替换次数 。 示例 1: 示例 2: 示例 3: 提示: 1 = n = 2^31 - 1 思路 这里我们

    2024年03月23日
    浏览(41)
  • 算法沉淀——贪心算法三(leetcode真题剖析)

    题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/ 给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。 在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。 返回 你能获得

    2024年03月24日
    浏览(32)
  • 算法沉淀——贪心算法六(leetcode真题剖析)

    题目链接:https://leetcode.cn/problems/broken-calculator/ 在显示着数字 startValue 的坏计算器上,我们可以执行以下两种操作: **双倍(Double):**将显示屏上的数字乘 2; **递减(Decrement):**将显示屏上的数字减 1 。 给定两个整数 startValue 和 target 。返回显示数字 target 所需的最小操

    2024年04月11日
    浏览(34)
  • 算法沉淀——贪心算法二(leetcode真题剖析)

    题目链接:https://leetcode.cn/problems/longest-increasing-subsequence/ 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如, [3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。 示例 1: 示

    2024年03月19日
    浏览(42)
  • leetcode系列贪心算法汇总

    11 盛水最多的容器 题目:给一个一维数组,大概的意思就是下标代表水槽的宽度,数组的值代表这个位置水槽的高度,求盛水最多的容量。 解析:肯定得有个临时变量来存最大值,且不断进行比较来更新最大值,然后分别从两边开始使用双指针进行遍历,tmp := (right - left)

    2024年02月07日
    浏览(35)
  • 【leetcode】贪心算法介绍

    详细且全面地分析贪心算法常用的解题套路、数据结构和代码逻辑如下: 找最值型: 每一步选择都是局部最优解,最后得到的结果就是全局最优解。 常用于找零钱问题、区间覆盖问题等。 一般情况下,可以通过排序将数据进行处理,然后逐步选择最优解。 区间问题: 将问

    2024年02月21日
    浏览(28)
  • 【贪心算法】leetcode刷题

    贪心算法无固定套路。 核心思想:先找局部最优,再扩展到全局最优。 两种思路: 1、从大到小。局部最优就是大饼干喂给胃口大的,充分利用饼干尺寸喂饱一个,全局最优就是喂饱尽可能多的小孩。 先遍历的胃口,在遍历的饼干 2、从小到大。 小饼干先喂饱小胃口 。两个

    2024年02月14日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包