力扣-柠檬水找零

103 阅读3分钟

「这是我参与2022首次更文挑战的第37天,活动详情查看:2022首次更文挑战」。

柠檬水找零

题目描述

在柠檬水摊上,每一杯柠檬水的售价为5美元。顾客排队购买你的产品,(按账单bills支付的顺序)一次购买一杯。
每位顾客只买一杯柠檬水,然后向你付5美元、10美元或20美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付5美元。
注意,一开始你手头没有任何零钱。
给你一个整数数组bills,其中bills[i]是第i位顾客付的账。如果你能给每位顾客正确找零,返回true,否则返回false
示例1:

输入:bills = [5,5,5,10,20]
输出:true
解释:
前 3 位顾客那里,我们按顺序收取 35 美元的钞票。
第 4 位顾客那里,我们收取一张 10 美元的钞票,并返还 5 美元。
第 5 位顾客那里,我们找还一张 10 美元的钞票和一张 5 美元的钞票。
由于所有客户都得到了正确的找零,所以我们输出 true

示例2:

输入:bills = [5,5,10,10,20]
输出:false
解释:
前 2 位顾客那里,我们按顺序收取 25 美元的钞票。
对于接下来的 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;
    }
}