贪心算法:柠檬水找零🍋

560 阅读3分钟

这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战

以前我也曾经刷过一段时间的leetcode,后来因为比较忙,所以停了好久了。现在来开始重新满满刷起来,毕竟只是位前端,还是继续使用JavaScript进行编写代码(最熟悉一些)

贪心算法

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解 。

贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择

我对于贪心算法的题目总是认为其解答是很巧妙的,有时候经常出乎你的意料,比如:《第三大的数,两地调度》,这里面两地调度的问题如果想通了,其实就非常简单,关键就是在于自己的思路。

柠檬水找零

柠檬水找零问题是贪心算法当中一道非常经典的问题

题目:leetcode地址

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

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

示例:

输入:bills = [5,5,5,10,20]

输出:true

解释: 前 3 位顾客那里,我们按顺序收取 3 张 5 美元的钞票。

第 4 位顾客那里,我们收取一张 10 美元的钞票,并返还 5 美元。

第 5 位顾客那里,我们找还一张 10 美元的钞票和一张 5 美元的钞票。

由于所有客户都得到了正确的找零,所以我们输出 true。

这道题目其实本身比较简单,主要就是看10元和20元的找零情况,当前我们所拥有的零钱是否满足需要找的零钱条件。

对应
5元不需要找零,直接收下
10元需要找零一张5元
20元两种方案:1. 一张5元 + 一张10元 2. 三张5元

本题在贪心算法上的运用就是在于20元的找零方案,是要使用哪一种更加好。贪心算法就是要达到局部最优解。

当然本题肯定是优先使用10 + 5这种方式,因为5元在这里是对10元和20元都通用的,而10元只是给20元会用到,所以肯定先消耗10元。

作答:(虽然我写的不一定是最优代码,但总算还是能够成功通过测试💎)

var lemonadeChange = function(bills) {
    // fives 5元数量, tens 10元数量
    let fives = 0, tens = 0;
    if (bills[0] != 5) return false;
    for(let item of bills) {
        if (item == 5) { fives ++; }
        else if (item == 10) {
            if (fives > 0) {
                fives --;
                tens ++;
            } else {
                return false;
            }
        } else if (item == 20) {
            if (tens > 0 && fives > 0) {
                fives --;
                tens --;
            } else if (fives > 2) {
                fives -= 3;
            } else {
                return false;
            }
        }
    }
    return true;
};