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

860.柠檬水找零

本题看上好像挺难,其实挺简单的,大家先尝试自己做一做。
https://programmercarl.com/0860.%E6%9F%A0%E6%AA%AC%E6%B0%B4%E6%89%BE%E9%9B%B6.html

第一印象

我想用哈希来存储,并同时记录一共多少钱,如果钱不够直接false。

钱够的话比如有2个10,要找15块钱,再去具体实现。

用一堆if else确实做出来了,但我觉得一点也不贪心。看看题解。

看完题解的思路

啊 原来找零20的时候优先用10+5的方式,然后再是5+5+5的方式就是贪心啊。

实现上的困难

没困难

感悟

贪心真是有时候让人……意想不到

代码随想录里说

因为美元10只能给账单20找零,而美元5可以给账单10和账单20找零,美元5更万能!

所以局部最优:遇到账单20,优先消耗美元10,完成本次找零。

全局最优:完成全部账单的找零。

局部最优可以推出全局最优,并找不出反例,那么就试试贪心算法!

代码

class Solution {
    public boolean lemonadeChange(int[] bills) {
        int total = 0;
        int[] money = new int[2];

        for (int i = 0; i < bills.length; i++) {
            if (bills[i] == 5) {
                total += 5;
                money[0]++;
            }

            if (bills[i] == 10) {
                total += 10;
                if (money[0] < 1) {
                    return false;
                } else {
                    money[0]--;
                    money[1]++;
                }
            }

            if (bills[i] == 20) {
                total += 20;
                if (money[0] >= 1 && money[1] >= 1) {
                    money[0]--;
                    money[1]--;
                } else if (money[0] >= 3) {
                    money[0] -= 3;
                } else {
                    return false;
                }
            }
        }

         return true;

    }
}

406.根据身高重建队列

本题有点难度,和分发糖果类似,不要两头兼顾,处理好一边再处理另一边。
https://programmercarl.com/0406.%E6%A0%B9%E6%8D%AE%E8%BA%AB%E9%AB%98%E9%87%8D%E5%BB%BA%E9%98%9F%E5%88%97.html

第一印象

哎卧槽题干就看不懂,看题解了。

看完题解的思路

这个题思路有点太难了。

[h, k] 也是两个维度。不能同时考虑两个,要先考虑一个再考虑一个。

先按身高排序,同身高的话,k增序排列。

在这里插入图片描述

之后再按 k 去调整位置。

**局部最优:**优先按身高高的people的k来插入。插入操作过后的people满足队列属性

**全局最优:**最后都做完插入操作,整个队列满足题目队列属性

实现中的困难

思路学会了我也写不出这个代码,草了。

chatgpt现在打不开,代码的实现回头再说。

感悟

代码随想录里的感悟:

关于出现两个维度一起考虑的情况,我们已经做过两道题目了,另一道就是135. 分发糖果 (opens new window)。

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

这道题目可以说比135. 分发糖果 (opens new window)难不少,其贪心的策略也是比较巧妙。

最后我给出了两个版本的代码,可以明显看是使用C++中的list(底层链表实现)比vector(数组)效率高得多。

对使用某一种语言容器的使用,特性的选择都会不同程度上影响效率。

所以很多人都说写算法题用什么语言都可以,主要体现在算法思维上,其实我是同意的但也不同意。

对于看别人题解的同学,题解用什么语言其实影响不大,只要题解把所使用语言特性优化的点讲出来,大家都可以看懂,并使用自己语言的时候注意一下。

对于写题解的同学,刷题用什么语言影响就非常大,如果自己语言没有学好而强调算法和编程语言没关系,其实是会误伤别人的。

这也是我为什么统一使用C++写题解的原因

代码

class Solution {
    public int[][] reconstructQueue(int[][] people) {
        // 身高从大到小排(身高相同k小的站前面)
        Arrays.sort(people, (a, b) -> {
            if (a[0] == b[0]) return a[1] - b[1];   // a - b 是升序排列,故在a[0] == b[0]的狀況下,會根據k值升序排列
            return b[0] - a[0];   //b - a 是降序排列,在a[0] != b[0],的狀況會根據h值降序排列
        });

        LinkedList<int[]> que = new LinkedList<>();

        for (int[] p : people) {
            que.add(p[1],p);   //Linkedlist.add(index, value),會將value插入到指定index裡。
        }

        return que.toArray(new int[people.length][]);
    }
}

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

本题是一道 重叠区间的题目,好好做一做,因为明天三道题目,都是 重叠区间。
https://programmercarl.com/0452.%E7%94%A8%E6%9C%80%E5%B0%91%E6%95%B0%E9%87%8F%E7%9A%84%E7%AE%AD%E5%BC%95%E7%88%86%E6%B0%94%E7%90%83.html

第一印象

感觉就是找交集呢 直接看下题解

看完题解的思路

思路就是重复的气球尽量用一个弓箭射。

为了让气球挨着重叠,就要先排序。

 Arrays.sort(points, (a, b) -> Integer.compare(a[0], b[0]));

gpt还没复活,这是一个升序。我不懂lambda表达式里用什么判断升序降序,return的正负吗????

难在怎么判断气球重复,以及我和上一个重复了,下一个和我们俩都重复吗?

  • 如果我的左边界 小于等于 上一个的右边界,我俩就算重叠了
  • 我和上一个最小的右边界,作为我俩的右边界 right,用于判断下一个和我是否重叠的时候,它的左边界如果和我俩最小的right都重叠,那它和我俩就重叠了。

比如1-4, 2-7, 5-6. 按照我的逻辑1-4 和2-7重叠,箭数量不变,但这个时候4就作为他俩新的右边界限了,和5-6是不重叠的。

实现时的困难

没有啥困难,就是Lambda表达式看不懂。

代码

class Solution {
    public int findMinArrowShots(int[][] points) {

        Arrays.sort(points, (a, b) -> Integer.compare(a[0], b[0]));

        int result = 1;

        for (int i = 1; i < points.length; i++) {
            //我的左边界超过 上一个的右边了
            if (points[i][0] > points[i - 1][1]) {
                result++;
            } else {
                //我和上一个是重复的,不需要多一个箭射我
                //更新我的右边界吧,用于判断下一个的时候,看能不能一个箭射我们仨
                points[i][1] = Math.min(points[i - 1][1], points[i][1]);
            }
        }

        return result;

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值