「这是我参与2022首次更文挑战的第37天,活动详情查看:2022首次更文挑战」。
柠檬水找零
题目描述
在柠檬水摊上,每一杯柠檬水的售价为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。
示例3:
输入: bills = [5,5,10]
输出: true
示例4:
输入: bills = [10,10]
输出: false
算法解析
本题可分为三种情况:
第一种情况:顾客支付5美元,这样可以直接收取钞票,不需要找零
第二种情况:顾客支付10美元,要给顾客找零5美元
第三种情况:顾客支付20美元,要给顾客找零,这种情况下找零有两种方案,一种是一张十元的,一张五元的,另外一种是三张五元的,由这两种方案可以看出在给顾客找零时我们对5美元的需求比10美元的需求要大一点,根据贪心策略,当发生第三种情况时,我们更倾向于用10美元和5美元来找零,因为5美元需求比10美元大,尽可能保留5美元的使用。
局部最优:给20美元找零,优先用10美元完成一次找零
全局最优:完成所有顾客的找零
代码解析
class Solution {
public boolean lemonadeChange(int[] bills) {
//定义5美元,10美元的个数
int five=0;
int ten=0;
//遍历bills整数数组
for(int i=0;i<bills.length;i++){
//第一种情况,收取5美元不需要找零,five个数加1
if(bills[i]==5){
five++;
//第二种情况,收取10美元,找零5美元,5美元个数减1,10美元个数加1
}else if(bills[i]==10){
five--;
ten++;
//第三种情况,收取20美元,找零有两种方案
}else if(bills[i]==20){
//第一种方案:如果有10美元的话,用一张10美元和一张5美元找零,10美元和5美元个数都减1
if(ten>0){
ten--;
five--;
//第二种方案:如果没有10美元的话,用三张5美元找零,5美元个数减去3
}else{
five-=3;
}
}
//以上的所有情况列举后,如果five或者ten的个数都小于0时,表示此次不能正确找零,返回false;大于或者等于0时,表示此次能正确找零,返回true
if(five<0||ten<0){
return false;
}
}
return true;
}
}