860-柠檬水找零(Lemonade Change)

本文探讨了一道经典的找零问题——柠檬水摊找零挑战。顾客使用5、10或20美元购买5美元一杯的柠檬水,摊主需正确找零。文章提供了两种解决方案,一种使用List存储零钱,另一种采用更高效的计数方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述
中文

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

英文

At a lemonade stand, each lemonade costs $5. 

Customers are standing in a queue to buy from you, and order one at a time (in the order specified by bills).

Each customer will only buy one lemonade and pay with either a $5, $10, or $20 bill.  You must provide the correct change to each customer, so that the net transaction is that the customer pays $5.

Note that you don't have any change in hand at first.

Return true if and only if you can provide every customer with correct change.

示例

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

解题思路

  • 找零问题,第一反应贪婪算法,如果能拿十元的找就用十元的找,否则用五元。而经过分析,第一位顾客只能用五元,否则的话就找不开,第二位顾客最多用十元否则找不开。
  • 有了思路以后就要贴一下代码了。
class Solution {
    public static boolean findMoney(List<Integer> change, int money){			//找零的方法
		if(money == 5){		//如果是五元,不用找零,直接放到钱柜chang
			change.add(money);
			return true;
		}
        if(money == 10 && change.indexOf(5) != -1){			//如果是十元并且钱柜有五元,就删掉一个五元,并把十元添加到钱柜
        	change.add(money);
        	change.remove(change.indexOf(5));
        	return true;
        }
        if(money == 20){					//如果是20元就有两种情况
        	if(change.indexOf(5) != -1 && change.indexOf(10)!= -1){			//如果有五元和十元,就可以找开
        		change.add(money);
        		change.remove(change.indexOf(5));
        		change.remove(change.indexOf(10));
        		return true;
        	}
        	else{				//否则有三张五元,也可以召开
        		int five = 0;
        		int[] five_location = new int[3];
        		for(int i = 0;i < change.size() && five < 3;i++){
        			if(change.get(i) == 5){
        				five_location[five++] = i;
        			}
        		}
        		if(five == 3){
        			for(int i = 0;i<five_location.length;i++){
        				change.remove(five_location[i] - i);
        			}
        			change.add(money);
        			return true;
        		}
        		
        	}
        }
        return false;			//剩下的情况都为false
    }
    public static boolean lemonadeChange(int[] bills) {
        List<Integer> change = new ArrayList<Integer>();
        if(bills[0] != 5)		//如果第一张不是五元,直接false
            return false;
        if(bills.length > 2 && bills[1] > 10)		//如果第二张是20,直接false
            return false;
        for(int i = 0;i < bills.length;i++){
        	if(!findMoney(change, bills[i]))
        		return false;					//中间有任何一次找不开,都返回false
        }
        return true;
        
    }
}
  • 因为增加了一个List用来放零钱和判断,所以效率十分低下。所以是不是有一种方法优化。
  • emmm,同为贪心为何你这么优秀,下面是一位别人的思路:整体思路差不多,但是只用了一个长度为三的数组来计数即可。
class Solution {
    public boolean lemonadeChange(int[] bills) {
        if(bills[0] != 5)
            return false;
        if(bills.length > 2 && bills[1] > 10)
            return false;
        int[] change = new int[3]; //用来标记5、10、20的张数
        for(int i = 0;i < bills.length;i++){
            switch(bills[i]){
            case 5:
            	change[0]++;
            	break;
            case 10:
            	if(--change[0] < 0)
            		return false;
            	change[1]++;
            	break;
            case 20:
            	if(change[0] <= 0)
            		return false;
            	else if(change[0] > 0 && change[1] > 0){
            		change[0]--;
            		change[1]--;
            	}
            	else if(change[0] >= 3){
					change[0] -= 3;
				}
                else {
					return false;
				}
            	change[2]++;
            	break;
            }
        }
        return true;
    }
}
**Python柠檬水找零问题** 这是一个经典的算法题,题目描述如下: 假设你正在经营一家柠檬水摊位,每个柠檬水的价格都是固定的5元。顾客们会用面值为5元、10元或20元的纸币来购买柠檬水。 你需要保证每次都能给顾客正确的找零,并且初始时你没有任何零钱可以用来找零。如果能够成功地为每一位顾客找到合适的零钱,则返回 `True`;如果有任何一位顾客无法得到正确的找零,则返回 `False`。 我们来看一下具体的解法步骤: ### 解法思路 我们可以维护两个变量分别记录手头上拥有的5元钞票的数量 (`five_count`) 和 10元钞票的数量 (`ten_count`) ,因为只需要考虑这两种情况即可完成所有的找零任务(注意:不存在需要找回40的情况)。每当遇到一个新的支付请求时,就依据当前收到的钱以及现有的零钱情况进行处理。 - 如果客户给出的是 **5元** 纸币——直接收下并增加手中相应的金额数目; - 若是收到 **10元** 的话,那么就要检查是否能从已有的现金里拿出一张 **5元** 来作为找头; - 当收到 **20元** 付款的时候有三种可能性: - 使用三张五元; - 或者是一张十元加一张五元组合起来凑齐这十五块差价; 最后遍历一遍所有交易后仍然保持了足够的小费来做之后可能出现的新订单的找零工作即表示此次模拟售卖过程可行。 下面是对应的 Python 实现代码示例: ```python def lemonade_change(bills): five = ten = 0 for bill in bills: if bill == 5: five += 1 elif bill == 10: # 检查是否有足够数量的5元来找零 if not five: return False else: five -= 1 ten += 1 else: # 这里代表bill==20的情形 if five and ten >= 1: five -= 1 ten -= 1 elif five >= 3: five -= 3 else: return False return True # 测试数据点 print(lemonade_change([5, 5, 5, 10, 20])) # 输出应为 True ``` 希望这个解答对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值