《代码随想录》Ⅷ 贪心算法 860. 柠檬水找零

《代码随想录》Ⅷ 贪心算法 860. 柠檬水找零

努力学习!

题目:力扣链接

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

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

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

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

一、思想

这道题的核心思想是使用贪心算法,即在每一步选择中,尽可能多地使用现有的零钱来进行找零,以确保能够满足后续的找零需求。具体来说,当顾客支付10元或20元时,优先使用10元进行找零,因为10元只能用于找零5元,而5元可以用于更多的找零场景。

二、代码

/**
 * 买卖柠檬ade问题
 * 有四种面值的钞票:5,10,20,100。
 * 你会得到一些钞票,然后需要返回正确的找零。
 * 给定一个整数数组 bills,其中 bills[i] 是顾客支付的钞票面值,你需要返回找零的钞票数目最少的情况下,钞票数目能否正好找齐。
 * 注意:
 * 1. 0 <= bills.length <= 10^4
 * 2. 1 <= bills[i] <= 10^4
 */
class Solution
{
public:
    /**
     * 判断是否能正好找齐
     * @param bills 支付的钞票面值数组
     * @return 是否能正好找齐
     */
    bool lemonadeChange(vector<int> &bills)
    {
        // 记录5元和10元的钞票数量
        int five = 0, ten = 0;

        // 遍历所有支付的钞票
        for (int i = 0; i < bills.size(); ++i) {
            // 如果是5元钞票,数量加一
            if (bills[i] == 5) {
                five++;
            }
            // 如果是10元钞票
            if (bills[i] == 10) {
                // 如果没有足够的5元钞票,返回false
                if (five <= 0) {
                    return false;
                }
                // 数量加一,5元钞票数量减一
                ten++;
                five--;
            }
            // 如果是20元钞票
            if (bills[i] == 20) {
                // 如果有足够的10元和5元钞票,数量减一,5元钞票数量减一
                if (ten > 0 && five > 0) {
                    ten--;
                    five--;
                }
                // 如果没有足够的10元和5元钞票,但有足够的5元钞票,数量减三
                else if (five >= 3) {
                    five -= 3;
                }
                // 如果既没有足够的10元和5元钞票,也没有足够的5元钞票,返回false
                else {
                    return false;
                }
            }
        }

        // 如果能正好找齐,返回true
        return true;
    }
};

三、代码解析

1. 算法工作原理分解
1.1 初始化零钱数量
  • 目的:记录当前拥有的5元和10元零钱的数量。
  • 实现:使用两个变量five​和ten​来分别记录5元和10元的数量,初始值均为0。
1.2 遍历支付账单
  • 目的:根据顾客支付的金额进行找零,并更新零钱数量。

  • 实现

    • 如果顾客支付5元,直接增加5元零钱的数量。
    • 如果顾客支付10元,检查是否有足够的5元零钱,如果有,则减少5元零钱的数量并增加10元零钱的数量;否则,返回false​。
    • 如果顾客支付20元,优先使用10元和5元进行找零(如果有),否则使用三个5元进行找零。如果都无法满足,则返回false​。
1.3 返回结果
  • 目的:判断是否能够成功完成所有找零。
  • 实现:如果遍历完所有账单后没有返回false​,则返回true​,表示能够成功完成所有找零。
2. 关键点说明
2.1 贪心算法的应用
  • 局部最优:在每一步找零时,尽可能多地使用现有的零钱,尤其是优先使用10元进行找零。
  • 全局最优:通过局部最优的选择,确保能够完成所有找零,并且零钱的使用是最优的。
2.2 零钱的使用顺序
  • 当顾客支付20元时,优先使用10元和5元进行找零,因为这样可以减少5元零钱的消耗,使得5元零钱能够用于更多的找零场景。
2.3 边界条件
  • 如果顾客支付10元或20元时,没有足够的零钱进行找零,则直接返回false​。

四、复杂度分析

  • 时间复杂度O(n)

    • 其中n​是账单的数量。算法只需要遍历一次账单数组,因此时间复杂度为O(n)​。
  • 空间复杂度O(1)

    • 只需要常数空间来记录5元和10元零钱的数量,因此空间复杂度为O(1)​。

白展堂:人生就是这样,苦和累你总得选一样吧?哪有什么好事都让你一个人占了呢。 ——《武林外传》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值