AlgoMooc
你已开通华为OD训练营权益,还差最后一步——完成入营激活(兑换课程 + 加飞书 + 登记服务群),即可解锁全部课程与专属服务。去激活 →
← OD 20 天课程

华为 OD 训练营 · 题解精讲

LC860. 柠檬水找零

配套讲解:视频讲解

LC860. 柠檬水找零 视频地址:https://uha.xet.tech/s/3Hi5qk

题目描述

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

题目解析

解题思路

本题模拟找零过程,核心是贪心策略:收到大面额钞票时,优先用大面额零钱找零,因为5元零钱更通用(既能找10元也能找20元)。用两个变量 fiveten 记录手中5元和10元钞票的数量(20元钞票不会用于找零,故无需记录)。

关键步骤

1. 遍历 bills 数组,对每位顾客的付款分情况处理:

  • 付5元:直接收下,five += 1
  • 付10元:必须找5元。若 five > 0,则 five -= 1, ten += 1;否则返回 false
  • 付20元:优先用一张10元和一张5元找零(ten > 0 and five > 0);若不行,再用三张5元(five >= 3);否则返回 false

2. 遍历结束后返回 true

找零决策树示意:


付20元时:
  有10元+5元? → 用10+5找零
  否则有3张5元? → 用三张5元找零
  否则 → 失败

复杂度分析

  • 时间复杂度:O(N),只需一次遍历 bills 数组。
  • 空间复杂度:O(1),仅用两个整数变量记录零钱数量。

参考代码

# 登录 AlgoMooc 官网获取更多算法图解
# https:#www.algomooc.com
# 作者:程序员吴师兄
# 代码有看不懂的地方一定要私聊咨询吴师兄呀
# 柠檬水找零( LeetCode 860 ):https:#leetcode-cn.com/problems/lemonade-change/
class Solution:
    def lemonadeChange(self, bills: List[int]) -> bool:
        # 用来记录 5 元钞票的数量
        five = 0

        # 用来记录 10 元钞票的数量
        ten = 0

        # 顾客开始按顺序购买,并找零
        for i  in range(len(bills)) : 
            # 1、如果发现是 5 元面额
            if bills[i] == 5 :
                # 那么可以直接收钱,不需要找零
                # 并且 5 元钞票的数量加 1
                five += 1

                # 2、如果发现是 10 元面额
            elif bills[i] == 10 :

                # 如果手中有 5 元钞票,则找零 5 元
                if five > 0 :
                    # 5 元钞票的数量减 1
                    five -= 1
                    # 10 元钞票的数量加 1
                    ten += 1
                else : 
                    # 如果手中没有 5 元钞票,说明找零失败
                    return False
    
                # 3、如果发现是 20 元面额
            else : 

                # 如果手中有 10 元 和 5 元钞票,则找零 1 张 10 元和 1 张 5 元的钞票
                if ten > 0 and five > 0 :
                    # 5 元钞票的数量减 1
                    five -= 1
                    # 10 元钞票的数量减 1
                    ten -= 1
                else:
                    # 如果手中只有 5 元的,并且数量超过或者等于 3 张
                    # 那么找零 3 张 5 元的钞票
                    if five >= 3 : 
                        # 5 元钞票的数量减 3
                        five -= 3
                    else :
                        # 说明这个时候顾客付 20 元的时候
                        # 1、手中没有 1 张 10 元的和 1 张 5 元的
                        # 2、手中没有 3 张 5 元的
                        # 说明找零失败
                        return False

        # 所有顾客都找零了,成功
        return True
四、复杂度分析
时间复杂度:O(N),其中 N 是 bills 的长度。
空间复杂度:O(1)。