代码随想录算法训练营第三十四天|LeetCode860,406,452

代码随想录算法训练营第三十四天|LeetCode860,406,452

860.柠檬水找零

第一思路:

5美元直接收下,10美元的找5美元的,20美元的先找10美元的,再找5美元的

20美元就是贪心的地方。

设置两个变量,分别记录5美元与10美元的数量,找零过程中有一个小于0那就代表找零失败

public static boolean lemonadeChange(int[] bills) {
        int count5 = 0;
        int count10 = 0;
        for (int bill:bills){
            switch (bill){
                case 5:
                    count5++;
                    break;
                case 10:
                    count5--;
                    if (count5<0){
                        return false;
                    }
                    count10++;
                    break;
                case 20:
                    count10--;
                    if (count10<0){
                        count10++;
                        count5 -= 3;
                        if (count5 < 0)
                            return false;
                    }else{
                        count5--;
                        if (count5<0){
                            return false;
                        }
                    }
                    break;
            }
        }
        return true;

406.根据身高重建队列 (*)

二维数组的排序怎么做?重写Arrays.sort里的compare

遇到两个维度权衡的时候,一定要先确定一个维度,再确定另一个维度。

如果两个维度一起考虑一定会顾此失彼,

要优先考虑哪个维度,一定是这个维度确定后,已经符合题目要求了,这就再去考虑另外一个维度

本题相信大家困惑的点是先确定k还是先确定h呢,也就是究竟先按h排序呢,还是先按照k排序呢?

如果按照k来从小到大排序,排完之后,会发现k的排列并不符合条件,身高也不符合条件,两个维度哪一个都没确定下来。

那么按照身高h来排序呢,身高一定是从大到小排(身高相同的话则k小的站前面),让高个子在前面。

此时我们可以确定一个维度了,就是身高,前面的节点一定都比本节点高!

而昨天分糖果的题,看上去从哪边开始比较都没有问题。

拍完身高以后怎么处理第二个值呢

那么只需要按照k为下标重新插入队列就可以了,为什么呢?

以图中{5,2} 为例:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zDA4skbd-1677658706547)(note.assets/20201216201851982.png)]

按照身高排序之后,优先按身高高的people的k来插入,后序插入节点也不会影响前面已经插入的节点,最终按照k的规则完成了队列。

所以在按照身高从大到小排序后:

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

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

  public int[][] reconstructQueue(int[][] people) {
        //身高从大到小排
        Arrays.sort(people, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                //如果两人身高一样,则k值较小的排在前面
                if (o1[0] == o2[0]){
                    return o1[1] - o2[1];
                }
                //正常情况下身高高的排在前面
                return o2[0] - o1[0];
            }
        });

        LinkedList<int[]> que = new LinkedList<>();
        //根据k值进行插入
        for (int[]p:people){
            que.add(p[1],p);
        }
        return que.toArray(new int[people.length][]);


    }

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

我的思路:

根据points的start对数组进行排序,然后遍历这个数组,使用一个数组range记录第一个气球的直径

如果当前的start落到了range的范围内,则继续判断下一个气球,当气球的起点不在range内的时候,就用这个气球的直径替换掉range,count值再加加

遍历完数组,返回值。

第一次错误:

没有考虑气球中出现了[0,6] [0,9] 这种起点范围一样的情况,这种情况下,将范围较小的气球排在前面,比如这种情况下就将[0,6] 排到[0,9]前面

第二次错误:

range实际上是在不断的发生改变的。每次找到一个符合条件的,range就要进行相应的收缩。

这样的话就不用考虑第一次错误进行的处理了,因为range会进行收缩的。

参考题解:直接在point上进行判断,时间复杂度要低一点。有重叠的就把points[i][1]换成最小值如果气球重叠了,重叠气球中右边边界的最小值 之前的区间一定需要一个弓箭

    public static int findMinArrowShots(int[][] points) {

        int count = 1;

        Arrays.sort(points,(a,b)->{
            if (a[0] < b[0]){
                return -1;
            }
            if (a[0] == b[0]){
                if (a[1] < b[1]){
                    return -1;
                }
            }
            return 1;
        });
        int[] range = points[0];
        for (int i  = 1; i<points.length;i ++ ){
            //下一个气球的起点落到了范围内
            if (points[i][0] >= range[0] && points[i][0] <= range[1]){
                range[0] = points[i][0];
                range[1] = Math.min(range[1],points[i][1]);
                continue;
            }
            //下一个起点不在范围内
            if(points[i][0] > range[1]){
                range = points[i];
                count++;
            }
        }
        return count;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值