860-柠檬水找零(Lemonade Change)

题目描述
中文

在柠檬水摊上,每一杯柠檬水的售价为 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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值