贪心:860. 柠檬水找零、406. 根据身高重建队列、452. 用最少数量的箭引爆气球

提示:努力生活,开心、快乐的一天


860. 柠檬水找零

题目链接:860. 柠檬水找零

💡解题思路

  1. 有如下三种情况:
    情况一:账单是5,直接收下。
    情况二:账单是10,消耗一个5,增加一个10
    情况三:账单是20,优先消耗一个10和一个5,如果不够,再消耗三个5
  2. 情况三这里是有贪心的,因为美元10只能给账单20找零,而美元5可以给账单10和账单20找零,美元5更万能!所以局部最优:遇到账单20,优先消耗美元10,完成本次找零。全局最优:完成全部账单的找零。

🤔遇到的问题

  1. 暂无

💻代码实现

贪心

var lemonadeChange = function (bills) {
    //统计5元、10元的张数
    let five = 0;
    let ten = 0;
    for (let bill of bills) {
        //情况一:5元账单
        if (bill === 5) {
            five++
        }
        //情况二:10元账单,找零5元
        else if (bill === 10) {
            if (five > 0) {
                ten++
                five--
            } else {
                return false
            }
        } else {
            //情况三:20元账单,找零10元+5元;找零3张5元
            if (ten > 0 && five > 0) {
                ten--
                five--
            } else if (five >= 3) {
                five -= 3
            } else {
                return false
            }
        }
    }
    return true
};

🎯题目总结

咋眼一看好像很复杂,分析清楚之后,会发现逻辑其实非常固定,如果一直陷入想从整体上寻找找零方案,就会把自己陷进去,各种情况一交叉,只会越想越复杂了。


406. 根据身高重建队列

题目链接:406. 根据身高重建队列

💡解题思路

  1. 有两个维度,h和k,看到这种题目一定要想如何确定一个维度,然后再按照另一个维度重新排列。如果按照k来从小到大排序,排完之后,会发现k的排列并不符合条件,身高也不符合条件,两个维度哪一个都没确定下来。
  2. 那么按照身高h来排序呢,身高一定是从大到小排(身高相同的话则k小的站前面),让高个子在前面。按照身高排序之后,优先按身高高的people的k来插入,后序插入节点也不会影响前面已经插入的节点,最终按照k的规则完成了队列。在这里插入图片描述
  3. 在按照身高从大到小排序后:
    局部最优:优先按身高高的people的k来插入。插入操作过后的people满足队列属性
    全局最优:最后都做完插入操作,整个队列满足题目队列属性

🤔遇到的问题

  1. 按照身高排序是需要注意,如果身高相同的话,k小的排在前面

💻代码实现

贪心

var reconstructQueue = function(people) {
    let queue = []
    //根据身高,从高到低排序
    people.sort((a, b) => {
        if (b[0] !== a[0]) {
            return b[0]-a[0]
        } else {
            return a[1]-b[1]
        }
    })
    //遍历数组,根据Ki值调整数组的位置
    for (let item of people) {
        queue.splice(item[1],0,item)
    }
    return queue
};

🎯题目总结

技巧都是确定一边然后贪心另一边,两边一起考虑,就会顾此失彼。


452. 用最少数量的箭引爆气球

题目链接:452. 用最少数量的箭引爆气球

💡解题思路

  1. 局部最优:当气球出现重叠,一起射,所用弓箭最少。全局最优:把所有气球射爆所用弓箭最少。
  2. 让气球尽可能的重叠,需要对数组进行排序
  3. 如果气球重叠了,重叠气球中右边边界的最小值 之前的区间一定需要一个弓箭。在这里插入图片描述

🤔遇到的问题

  1. 目中说的是:满足 xstart ≤ x ≤ xend,则该气球会被引爆。那么说明两个气球挨在一起不重叠也可以一起射爆,if (points[i][0] > points[i - 1][1]) 不能是>=

💻代码实现

贪心

var findMinArrowShots = function (points) {
    if (points.length == 0) return 0
    //起始位置从小到大排序
    points.sort((a, b) => {
        return a[0] - b[0]
    })
    let result = 1// points 不为空至少需要一支箭
    for (let i = 1; i < points.length; i++) {
         // 气球i和气球i-1不挨着,注意这里不是>=
        if (points[i][0] > points[i - 1][1]) {
            result++// 需要一支箭
        } else {// 气球i和气球i-1挨着
            // 更新重叠气球最小右边界
            points[i][1] = Math.min(points[i - 1][1], points[i][1])
        }
    }
    return result
};

🎯题目总结

如果真实的模拟射气球的过程,应该射一个,气球数组就remove一个元素,这样最直观,毕竟气球被射了。
但仔细思考一下就发现:如果把气球排序之后,从前到后遍历气球,被射过的气球仅仅跳过就行了,没有必要让气球数组remove气球,只要记录一下箭的数量就可以了。

🎈今日心得

代码实现都不难,但是思路确实很难想到

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值