算法:
本题仔细一琢磨就会发现,可供我们做判断的空间非常少!
只需要维护三种金额的数量,5,10和20。
有如下三种情况:
- 情况一:账单是5,直接收下。
- 情况二:账单是10,消耗一个5,增加一个10
- 情况三:账单是20,优先消耗一个10和一个5,如果不够,再消耗三个5
此时大家就发现 情况一,情况二,都是固定策略,都不用我们来做分析了,而唯一不确定的其实在情况三。
其实情况三这里是有贪心的。
账单是20的情况,为什么要优先消耗一个10和一个5呢?
因为美元10只能给账单20找零,而美元5可以给账单10和账单20找零,美元5更万能!
局部最优:遇到账单20,优先消耗美元10,完成本次找零。
全局最优:完成全部账单的找零。
正确代码:
class Solution {
public boolean lemonadeChange(int[] bills) {
int five = 0;
int ten = 0;
for (int i = 0; i< bills.length; i++){
if (bills[i]==5) five++;
else if (bills[i]==10) {
if (five == 0) {return false;}
five--;
ten++;
}
else if (bills[i]==20){
if(ten>0 && five >0){
ten--;
five--;
}
else if (five>=3){
five-=3;
}else return false;
}}
return true;
}
}
注意:
顾客的出现是有先后顺序的。比如[10,5,5,5]。当第一个顾客出现时,当前无法找零,即使后面的顾客送来了5,但是第一个顾客也无法找零,所以要return false;
时间空间复杂度:
- 时间复杂度: O(n)
- 空间复杂度: O(1)