题目描述
在柠檬水摊上,每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。
每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。
注意,一开始你手头没有任何零钱。
给你一个整数数组 bills ,其中 bills[i] 是第 i 位顾客付的账。如果你能给每位顾客正确找零,返回 true ,否则返回 false 。
分析
输入:Array,根据客户给的钱形成的零钱数组
输出:Boolean,是否可以找零
解题思路
如果给我们 5 元,就直接收下,10 元需要找 5 元。关键点是,如果给我们 20 元,应该怎么处理呢?
我们可以发现,这时候既可以找一张 5 元,一张 10 元。也可以找 3 张 5 元。显然,我们应当优先地去找一张 5元,一张 10 元,因为 5 元的应用场景更多,一旦被用光 10 元就找不开了~
所以这里实际上是贪心的思想,能够找 10 + 5 的局部最优解,就优先这么做。
再找钱的过程中,如果遇到需要的钱 💰 没有的情况,我们直接返回 false,在所有的顾客都找零完毕的情况下,我们认为找零成功,返回 true。
代码
/**
* @param {number[]} bills
* @return {boolean}
*/
var lemonadeChange = function (bills) {
let five = 0,
ten = 0
for (bill of bills) {
if (bill === 5) {
// 有 5 元进账
five++
} else if (bill === 10) {
// 没有找零用的 5 元,返回 false
if (!five) return false
// 10 元增加,5 元减少
ten++
five--
} else {
// 20 元的分类讨论
// 10 元和 5 元找零
if (ten && five) {
ten--
five--
} else if (five >= 3) {
// 五元找零
five -= 3
} else {
// 都不能找开
return false
}
}
}
return true
}
复杂度
时间:O(N), 需要遍历一遍数组 空间:O(1), 需要存储 5,10 元剩余的张数