[路飞]860. 柠檬水找零

184 阅读2分钟

题目描述

在柠檬水摊上,每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。

每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。

注意,一开始你手头没有任何零钱。

给你一个整数数组 bills ,其中 bills[i] 是第 i 位顾客付的账。如果你能给每位顾客正确找零,返回 true ,否则返回 false 。

分析

输入:Array,根据客户给的钱形成的零钱数组
输出:Boolean,是否可以找零

解题思路

如果给我们 5 元,就直接收下,10 元需要找 5 元。关键点是,如果给我们 20 元,应该怎么处理呢?

我们可以发现,这时候既可以找一张 5 元,一张 10 元。也可以找 3 张 5 元。显然,我们应当优先地去找一张 5元,一张 10 元,因为 5 元的应用场景更多,一旦被用光 10 元就找不开了~

所以这里实际上是贪心的思想,能够找 10 + 5 的局部最优解,就优先这么做。

再找钱的过程中,如果遇到需要的钱 💰 没有的情况,我们直接返回 false,在所有的顾客都找零完毕的情况下,我们认为找零成功,返回 true

代码

/**
 * @param {number[]} bills
 * @return {boolean}
 */
var lemonadeChange = function (bills) {
  let five = 0,
    ten = 0

  for (bill of bills) {
    if (bill === 5) {
    // 有 5 元进账
      five++
    } else if (bill === 10) {
        // 没有找零用的 5 元,返回 false
      if (!five) return false

        // 10 元增加,5 元减少
      ten++
      five--
    } else {
      // 20 元的分类讨论
      // 10 元和 5 元找零
      if (ten && five) {
        ten--
        five--
      } else if (five >= 3) {
      // 五元找零
        five -= 3
      } else {
      // 都不能找开
        return false
      }
    }
  }

  return true
}

复杂度

时间:O(N), 需要遍历一遍数组 空间:O(1), 需要存储 5,10 元剩余的张数