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+篇,公众号对话框回复【数据结构与算法】、【算法】、【数据结构】中的任一关键词,获取系列文章合集。

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

posted @ 2019-05-11 22:22  程序员小川  阅读(604)  评论(0编辑  收藏  举报