当前位置: 首页 > article >正文

数据结构与算法之贪心: LeetCode 860. 柠檬水找零 (Typescript版)

柠檬水找零

  • https://leetcode.cn/problems/lemonade-change/

描述

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

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

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

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

示例 1

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

示例 2

输入:bills = [5,5,10,10,20]
输出:false
解释:
前 2 位顾客那里,我们按顺序收取 2 张 5 美元的钞票。
对于接下来的 2 位顾客,我们收取一张 10 美元的钞票,然后返还 5 美元。
对于最后一位顾客,我们无法退回 15 美元,因为我们现在只有两张 10 美元的钞票。
由于不是每位顾客都得到了正确的找零,所以答案是 false。

提示

  • 1 <= bills.length <= 1 0 5 10^5 105
  • bills[i] 不是 5 就是 10 或是 20

算法实现

1 )一般思路

function lemonadeChange(bills: number[]): boolean {
    // 表示自己的钱箱(用于存储零钱)
    const box: number[] = [];
    // 判断是否有顾客还在
    while (bills.length) {
        // 取出当前排在最前面顾客的钱
        const money: number = bills.shift();
        // 这种情况不需要找零
        if (money === 5) {
            box.push(money);
        } else {
            // 手里的零钱要降序排列也就说最大的面值的钱放在最前面
            box.sort((a, b) => b - a);
            // 顾客的钱减去饮料的钱就是需要找给顾客的零钱
            let change = money - 5;
            for (let i = 0, len = box.length; i < len; i++) {
                if (box[i] <= change) {
                    change -= box[i];
                    box.splice(i, 1);
                    // 删除了元素,数组的长度发生了变化,要维持刚才的i不变
                    i--;
                }
                if (change === 0) break;
            }
            // 没有足够的零钱找给顾客
            if (change !== 0) return false;
            // 顾客的钱存起来
            box.push(money);
        }
    }
    return true;
};
  • 这种贪心策略,没有任何技巧
  • 这种算法耗时很严重,时间复杂度 O( n 2 l o g n n^2logn n2logn)
  • 上面这种思路就很复杂了,不推荐这种算法

2 )分类讨论

function lemonadeChange(bills: number[]): boolean {
    // 准备 5元,10元面值的钱,用于标识是否有对应的零钱
    let five: number = 0, ten: number = 0;
    // 遍历所有的客户付款
    for (const bill of bills) {
        // 匹配客户付款5元的场景: 不用找零
        if (bill === 5) {
            five += 1;
        // 匹配客户付款10元的场景: 找零5元,进账10元
        } else if (bill === 10) {
            if (five === 0) return false;
            five -= 1;
            ten += 1;
        // 匹配客户付款20元的场景: 找零15,进账20(不用处理, 这20元无法用于找零), 有两种情况
        } else {
            // 情况1: 5元和10元的组合
            if (five > 0 && ten > 0) {
                five -= 1;
                ten -= 1;
            // 情况2: 没有10元的情况下, 使用三张5元的
            } else if (five >= 3) {
                five -= 3;
            // 否则找零失败,返回 false
            } else return false;
        }
    }
    return true;
};
  • 这种是官方提供思路
  • 由于顾客只可能给你三个面值的钞票,而且我们一开始没有任何钞票
  • 因此我们拥有的钞票面值只可能是 5 美元,10 美元和 20 美元三种
  • 我们所能找零的面值也就只有 5 美元 和 10美元 两种面值的组合
  • 基于分类讨论的方式,列举了可能得找零场景,一个循环就搞定
  • 时间复杂度:O(N),其中 N 是 bills 的长度
  • 空间复杂度:O(1),常数空间,只用了2个变量,所以是O(1)
    • 备注: O(2)也用O(1)来表示,常数都是O(1)

http://www.kler.cn/news/148576.html

相关文章:

  • 云服务器哪家便宜?亚马逊AWS等免费云服务器推荐
  • 【Python百宝箱】密码学之美:Python安全性实战手册
  • TMUX设置鼠标滚轮滑动来浏览之前的前面内容--复制文字
  • java: Internal error in the mapping processor: java.lang.NullPointerException
  • 精通Nginx(18)-FastCGI/SCGI/uWSGI支持
  • 人工智能|机器学习——机器学习如何判断模型训练是否充分
  • JMeter+Python 实现异步接口测试
  • C++STL库常用详解与原理
  • Python与ArcGIS系列(十三)UpdateCursor方法
  • 吉他初学者学习网站搭建系列(3)——如何实现吉他在线调音
  • 微信可以添加多少好友?
  • 每日一题:LeetCode-105.从前序遍历与中序遍历构造二叉树
  • MySQL--日志
  • java实现从json字符串中解析指定的key值
  • Hibernate 脏检查和刷新缓存机制
  • Go 数字类型
  • MySQL INSERT插入条件判断:如果不存在则插入
  • 《golang设计模式》第三部分·行为型模式-08-状态模式(State)
  • LeetCode-面试题08.01 三步问题 C/C++实现 超详细思路及过程[E]
  • 【云栖 2023】姜伟华:Hologres Serverless 之路——揭秘弹性计算组
  • MySQL学习day03
  • 9.增删改操作
  • [autojs]ui线程中更新控件的值的问题
  • 中小型公司如何搭建运维平台,rancher、kubersphere、rainbond
  • 漏洞环境靶场搭建(内含DVWA SQLi-LABS upload-labs等)
  • mybatis <include refid=“xxx“></include>
  • 【每日一题】1457. 二叉树中的伪回文路径-2023.11.25
  • 142. 环形链表 II --力扣 --JAVA
  • linux 提权
  • XML Schema中的simpleContent 元素