本文正在参与掘金团队号上线活动,点击 查看大厂春招职位
题目描述
在柠檬水摊上,每一杯柠檬水的售价为 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元的找零问题:
- 顾客给了5元,不需要找零并且我们拥有的零钱5元增加了一张。
- 顾客给了10元,我们需要找零5月一张并且拥有的零钱10元增加了一张。
- 顾客给了20元
- 我们可以给一张10元和一张5元,在可以的条件下,我们应该优先选择这样的方案
- 在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
};