贪心算法-柠檬水找零|刷题打卡

172 阅读2分钟

本文正在参与掘金团队号上线活动,点击 查看大厂春招职位

题目描述

在柠檬水摊上,每一杯柠檬水的售价为 5 美元。

顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。

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

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

如果你能给每位顾客正确找零,返回 true ,否则返回 false 。

来源:力扣(LeetCode)

题目分析

思路分享

按照贪心算法的分析流程,我们先用数学语言描述问题,假设我们拥有的零钱数组money[0,0,0],其中的元素分别表示5、10、20元的数量,顾客给钱的顺序为数字pay[]

接着我们把场景简化,只考虑顾客给n元(记住n只能是5、10、20),此时我们拥有零钱money[0,0,0]我们该怎么给顾客找零。

找零的最优解是每次尽量把大额的钱找给顾客,在我们当前的场景下,我们只需要处理5、10、20元的找零问题:

  1. 顾客给了5元,不需要找零并且我们拥有的零钱5元增加了一张。
  2. 顾客给了10元,我们需要找零5月一张并且拥有的零钱10元增加了一张。
  3. 顾客给了20元
    1. 我们可以给一张10元和一张5元,在可以的条件下,我们应该优先选择这样的方案
    2. 在1无法满足时,我们可以使用3张5元的方案替代。

找零的方案有了,原本的场景不过是找零方案次数的增加而已,使用我们的思路,多次处理就可以了。

代码实现

function lemonadeChange(bills: number[]): boolean {
    let count5 = 0
    let count10 = 0
    function change(n) {
        if (n === 5) {
            count5++
            return true
        }
        if (n === 10 && count5 >= 1) {
            count10++
            count5--
            return true
        }
        if (n === 20 && count10 >= 1 && count5 >= 1) {
            count5--
            count10--
            return true
        }
        if (n === 20 && count5 >= 3) {
            count5 = count5 - 3
            return true
        }
        return false
    }
    for (let i = 0; i < bills.length; i++) {
        if (!change(bills[i])) {
            return false
        }
    }
    return true
};