• LeetCode.860-卖柠檬水找零(Lemonade Change)


    这是悦乐书的第331次更新,第355篇原创

    01 看题和准备

    今天介绍的是LeetCode算法题中Easy级别的第201题(顺位题号是860)。在柠檬水摊上,每杯柠檬水的价格为5美元。客户站在队列中向您购买,一次只买一杯(按照账单数组指定的顺序)。

    每位顾客只会购买一瓶柠檬水,并以5美元,10美元或20美元的钞票付款。您必须向每个客户提供正确的找零,以便净交易是客户支付5美元。请注意,您最初没有任何零钱。当且仅当您能为每位客户提供正确的找零时,才返回true。例如:


    输入:[5,5,5,10,20]
    输出:true
    说明:
    从前3位客户,我们按顺序收取3张5美元的钞票。
    从第四位客户那里,我们收取10美元的钞票并找零5美元。
    从第五位客户那里,我们收取10美元的钞票并找零5美元。
    由于所有客户都得到了正确的找零,我们输出true。


    输入:[5,5,10]
    输出:true


    输入:[10,10]
    输出:false


    输入:[5,5,10,10,20]
    输出:false
    说明:
    从前两位客户订购,我们收取两张5美元的钞票。
    对于接下来的两个客户,我们收取10美元的钞票并找零5美元。
    对于最后一位客户,我们不能给予15美元的找零,因为我们只有两张10美元的钞票。
    由于并非每个客户都收到正确的更改,因此返回false。


    注意

    • 0 <= bills.length <= 10000
    • bills[i]将是5,10或20。

    本次解题使用的开发工具是eclipse,jdk使用的版本是1.8,环境是win7 64位系统,使用Java语言编写和测试。

    02 第一种解法

    这是一个找零的问题。每杯柠檬水5块钱,顾客会用5块、10块、20块三种面值的钱购买柠檬水,顾客支付10块时,需要找零钱5块,如果是20块的,就需要找零钱15块,从而保证每笔交易都是5块。也就是说遇到大面值的钱时,你要有足够的小面值钱找零,找不出来就直接返回false。

    我们只需要记录5块和10块面值的钱有多少即可。

    收到5块时,5块的数量加1。

    收到10块时,10块的数量加1,5块的数量减1(找给顾客5块)。

    收到20块时,此时需要考虑两种不同的找零方式:

    1. 找给顾客一张10块的和一张5块的。
    2. 找给顾客3张5块的。

    每进行一次交易,我们都需要检查一次5块钱和10块钱的数量,如果减少到为负数,说明不能正常进行下一次交易了,直接返回false。最后返回true。

    此解法的时间复杂度是O(N),空间复杂度是O(1)。

    public boolean lemonadeChange(int[] bills) {
        int n = bills.length;
        int count5 = 0, count10 = 0;
        for (int bill : bills) {
            if (bill == 5) {
                count5++;
            } else if (bill == 10) {
                count10++;
                count5--;
            } else if (bill == 20) {
                if (count10 == 0 && count5 >= 0) {
                    count5 -= 3;
                } else {
                    count10--;
                    count5--;
                }
            }
            if (count5 < 0 || count10 < 0) {
                return false;
            }
        }
        return count5 >= 0 && count10 >= 0;
    }
    

    03 第二种解法

    使用递归的方式。

    针对上面的解法,同样的思路,也可以利用递归的方式来解,判断的条件依旧。

    此解法的时间复杂度是O(N),空间复杂度是O(1)。

    public boolean lemonadeChange(int[] bills) {
        return helper(bills, 0, 0, 0);
    }
    
    public boolean helper(int[] bills, int i, int five, int ten){
        if (i == bills.length) {
            return true;
        }
        if (bills[i] == 5) {
            return helper(bills, i+1, five+1, ten);
        }
        // 此处需要判断5块的数量是否大于0
        if (bills[i] == 10) {
            return five > 0 && helper(bills, i+1, five-1, ten+1);
        }
        if (ten > 0 && five > 0 ) { 
            return helper(bills, i+1, five-1, ten-1);
        } else if (five >= 3) {
            return helper(bills, i+1, five-3, ten);
        } else {
            return false;
        }
    }
    

    04 小结

    算法专题目前已连续日更超过五个月,算法题文章201+篇,公众号对话框回复【数据结构与算法】、【算法】、【数据结构】中的任一关键词,获取系列文章合集。

    以上就是全部内容,如果大家有什么好的解法思路、建议或者其他问题,可以下方留言交流,点赞、留言、转发就是对我最大的回报和支持!

  • 相关阅读:
    C语言|博客作业02
    少走弯路的十条忠告
    怎么算是优秀的程序员写给工作2,3年了的同行
    .NET世界的M型化原文作者奚江华
    工作以后十不要 减少奋斗30年
    <转>[创业经验]程序员创业:我的软件推广成功之路
    一个程序员的C#命名规则<转>
    推荐奚江华著《圣殿祭祀ASP.NET 3.5 专家技术手册 C#篇及他的TW博客进入方法》
    C#算法
    使用 DataFormatString 属性来提供列中各项的自定义格式
  • 原文地址:https://www.cnblogs.com/xiaochuan94/p/10850345.html
Copyright © 2020-2023  润新知