算法学习第二天

170 阅读2分钟

  由于leetcode题库的顺序不是按难易程序来排序的,按照顺序来上手难度有点大。所以目前会优先从简单题目中选择题目,后面再选择中等难度以及困难难度。今天选择的题目是第860题-柠檬找水,先看题目:

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

  这道题的标签是“贪心算法”,何为贪心算法?先来看看它的定义:在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解。
  定义有点懵,直接开始做题。看到这道题的时候的第一反应是:这个看起来简单,但应该怎样转化成代码!后面就想到用一个对象当做钱包,把收到的钱给存起来,于是说干就干,直接上代码:

var lemonadeChange = function(bills) {
    if (bills[0] >= 10 || bills[1] >= 20 || bills[2] >= 20) return false
    const wallet = {
        5: 0,
        10: 0,
        20: 0
    }
    for (let i = 0; i < bills.length; i++) {
        if (bills[i] === 5) {
            wallet[5]++
        } else if (bills[i] === 10) {
            if (wallet[5] > 0) {
                wallet[10]++
                wallet[5]--
            } else {
                return false
            }
        } else if (bills[i] === 20) {
            if (wallet[10] > 0 && wallet[5] > 0) {
                wallet[10]--
                wallet[5]--
                wallet[20]++
            } else if (wallet[10] == 0 && wallet[5] >= 3) {
                wallet[5] -= 3
                wallet[20]++
            } else {
                return false
            }
        }
    }
    return true
};

  经过一轮调试,算是通过了。但这代码也太长了,一点都不优雅,再优化一下。参考一下leetcode官方的题解,其实20元这个变量是不会用到的,所以可以去掉:

var lemonadeChange = function(bills) {
    let five = 0; let ten = 0;
    for (let i = 0; i < bills.length; i++) {
        if (bills[i] === 5) {
            five++
        } else if (bills[i] === 10) {
            if (five === 0) return false
            five--; ten++;
        } else {
            if (ten > 0 && five > 0) {
                ten--;five--;
            } else if (ten == 0 && five >= 3) {
                five -= 3
            } else {
                return false
            }
        }
    }
    return true
};

  再回过头来看看这道题,目前是把问题给拆成3份,当用户给的是5美金有什么应对方式;当用户给的是10美金又是怎样应对,相应的20美金同理。贪心算法就是针对当前问题给出最优解,从而希望能达到全局的最优。
  今天这题,题目简单,难就难在如何理解贪心算法的概念。所以平时工作中,可以经常用到某种算法,只是不知道这种算法的定义。就好比突然看到某个自己经常说出口,但从没写过的字,恍然大悟:原来这个字是这样写的。