当前位置: 首页 > 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/a/148576.html

相关文章:

  • SOLIDWORKS代理商鑫辰信息科技
  • const限定符-C语言中指针的“可变与不可变”法则
  • 【测试框架篇】单元测试框架pytest(1):环境安装和配置
  • 【Qt】Macbook M1下载安装
  • 智享AI 无人自动直播的崛起 ,引领智能互动与自动带货新潮流!
  • 实战指南:理解 ThreadLocal 原理并用于Java 多线程上下文管理
  • 云服务器哪家便宜?亚马逊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 之路——揭秘弹性计算组