该题我的第一思路是模拟该题找钱的一个过程,首先我们面对收到5元的话,我们就直接收下,再使用嵌套循环来遍历bills的同时我们从我们拥有的最大面额的钱开始遍历,看看能不能找给顾客(因为在该题中5元是比较珍贵的,毕竟需要使用 5 美元的找零场景会比需要使用 10 美元的找零场景多,我们需要尽可能保留 5 美元的钞票),同时对我们的钱数和要找的钱数进行更新,直到完整找给顾客钱
下面就是代码实现
class Solution {
public://模拟
bool lemonadeChange(vector<int>& bills) {
if (bills[0] != 5)
{
return false;
}
int mymoney[25] = { 0 };
int i = 0, t = 0;
while (bills[i] == 5)
{
mymoney[5]++;//5美金的数量
i++;
}
for (int j = i; j < bills.size(); j++)
{
int to_cust = bills[j] - 5;//需要找给顾客的钱
for (int z = 10; z > 0; z -= 5)//从我最大的钱开始看能不能找
{
int need = to_cust / z;//这种钱需要多少张
if (need && mymoney[z] >= need)//需要这种钱且我有
{
to_cust -= (z * need);//需要找的钱减少
mymoney[z] -= need;
//我的钱增加了和减少了
}
if (to_cust == 0)
{
t++;
break;
}
}
if (to_cust != 0)
{
return false;
}
mymoney[bills[j]]++;//我收到顾客的钱
}
if (t == (bills.size()-(i)))
{
return true;
}
else
{
return false;
}
}
};
下面这个思路是在LeetCode上面的官方题解思路:直接分类讨论
由于顾客只可能给你三个面值的钞票,而且我们一开始没有任何钞票,因此我们拥有的钞票面值只可能是 5 美元,10 美元和 20 美元三种。基于此,我们可以进行如下的分类讨论。
- 5 美元,由于柠檬水的价格也为 5 美元,因此我们直接收下即可。
- 10 美元,我们需要找回 55美元,如果没有 5 美元面值的钞票,则无法正确找零。
- 20 美元,我们需要找回 15 美元,此时有两种组合方式,一种是一张 10 美元和 5 美元的钞票,一种是 3张 5 美元的钞票,如果两种组合方式都没有,则无法正确找零。当可以正确找零时,两种找零的方式中我们更倾向于第一种,即如果存在 5美元和 10 美元,我们就按第一种方式找零,否则按第二种方式找零,因为需要使用 5 美元的找零场景会比需要使用 10 美元的找零场景多,我们需要尽可能保留 5美元的钞票。
基于此,我们维护两个变量 five 和 ten 表示当前手中拥有的 5美元和 10 美元钞票的张数,从前往后遍历数组分类讨论即可。
class Solution {
public:
bool lemonadeChange(vector<int>& bills) {
int five=0,ten=0;
for(int i=0;i<bills.size();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)//优先用10元和5元的组合
{
ten--;
five--;
}
else if(five>=3)
{
five-=3;
}
else
{
return false;
}
}
}
return true;
}
};