LeetCode 打卡day35--柠檬水找零, 用最少数量的箭引爆气球, 根据身高重建队列


知识总结

贪心算法, 用局部最优推出全局最优


Leetcode 860. 柠檬水找零

题目链接

题目说明

在柠檬水摊上,每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。

每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。

注意,一开始你手头没有任何零钱。

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

在这里插入图片描述

代码说明

记录五元和十元的张数即可.

class Solution {
    
    
    public boolean lemonadeChange(int[] bills) {
    
    
        int[] freq = new int[2];
        for(int bill : bills){
    
    
            if(bill == 5){
    
    
                freq[0]++;
            }
            else if(bill == 10){
    
    
                if(freq[0] < 0) return false;
                freq[0]--;
                freq[1]++;
            }else{
    
    
                if(freq[1] >= 1 && freq[0] >=1){
    
    
                    freq[0]--;
                    freq[1]--;
                }else if(freq[0] >= 3){
    
    
                    freq[0] -= 3;
                }else{
    
    
                    return false;
                }
            }
        }
        return true;
    }
}

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

题目链接

扫描二维码关注公众号,回复: 15690969 查看本文章

题目说明

有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points ,其中points[i] = [xstart, xend] 表示水平直径在 xstart 和 xend之间的气球。你不知道气球的确切 y 坐标。

一支弓箭可以沿着 x 轴从不同点 完全垂直 地射出。在坐标 x 处射出一支箭,若有一个气球的直径的开始和结束坐标为 xstart,xend, 且满足 xstart ≤ x ≤ xend,则该气球会被 引爆 。可以射出的弓箭的数量 没有限制 。 弓箭一旦被射出之后,可以无限地前进。

给你一个数组 points ,返回引爆所有气球所必须射出的 最小 弓箭数 。
在这里插入图片描述

代码说明

方法1 :
这道题和之前的合并区间有点像, 可以用类似的方法, 但是这次新加入的区间不是并集, 而是交集. 如果没有相交的部分, 那么新增添一个区间进入list. 学习排序的写法, 直接写减法会存在Interger 最大值的越界问题, 所有重写compare方法.

class Solution {
    
    
    public int findMinArrowShots(int[][] points) {
    
    
        if(points.length == 1){
    
    
            return 1;
        }

        // Arrays.sort(points, 
        //     (a1, a2) -> a1[0] - a2[0]
        // );

		// 按照左边界的大小排序
        Arrays.sort(points, new Comparator<int[]>(){
    
    
            public int compare(int[] point1, int[] point2){
    
    
                if(point1[0]> point2[0]){
    
    
                    return 1;
                }else if (point1[0] < point2[0]){
    
    
                    return -1;
                }else{
    
    
                    return 0;
                }
            }
        });

        LinkedList<int[]> list = new LinkedList<>();
        int left =0, right = 0;
        list.add(points[0]);
        for(int i = 1; i < points.length; i++){
    
    
            left = points[i][0]; 
            right = points[i][1];
            if(left<= list.getLast()[1]){
    
    
                list.getLast()[0] = Math.max(list.getLast()[0], left);
                list.getLast()[1] = Math.min(list.getLast()[1], right);

            }else{
    
    
                list.add(points[i]);
            }
        }
        return list.size();
    }
}

方法2;
不同于上面, 我们按照有边界的大小升序排序. 那么为了尽可能多的射中更多的气球, 我们会射的位置为第一个的最右边, 然后如果一个新区间的左边界大于这个pos, 说明原来的箭射不中该区间, 需要重新射出新的箭.
在这里插入图片描述

class Solution {
    
    
    public int findMinArrowShots(int[][] points) {
    
    
        if(points.length == 1){
    
    
            return 1;
        }

        // Arrays.sort(points, 
        //     (a1, a2) -> a1[1] - a2[1]
        // );
			
        Arrays.sort(points, new Comparator<int[]>(){
    
    
            public int compare(int[] point1, int[] point2){
    
    
                if(point1[1]> point2[1]){
    
    
                    return 1;
                }else if (point1[1] < point2[1]){
    
    
                    return -1;
                }else{
    
    
                    return 0;
                }
            }
        });

        int pos = points[0][1];
        int ans = 1;
        for(int[] bollon : points){
    
    
            if(bollon[0] > pos){
    
    
                pos = bollon[1];
                ans++;
            }
        }
        return ans;
    }
}


Leetcode 406. 根据身高重建队列

题目链接

题目说明

假设有打乱顺序的一群人站成一个队列,数组 people 表示队列中一些人的属性(不一定按顺序)。每个 people[i] = [hi, ki] 表示第 i 个人的身高为 hi ,前面 正好 有 ki 个身高大于或等于 hi 的人。

请你重新构造并返回输入数组 people 所表示的队列。返回的队列应该格式化为数组 queue ,其中 queue[j] = [hj, kj] 是队列中第 j 个人的属性(queue[0] 是排在队列前面的人)。

在这里插入图片描述

代码说明

先花时间把题目读懂, 排序后应该的[5, 0] 表示, 这个人身高为5, 前面身高>=5的人有0 个

解题还是挺难的, 然后许多Java代码的技巧和语法糖.

  1. 先按身高再按k值排序
        Arrays.sort(people,
            (a, b) -> {
                if(a[0] == b[0]) return a[1] - b[1]; // 身高相同, k值升序排列
                return b[0] - a[0]; // 否则优先按身高降序排列
            }
        );
  1. 指定位置插入元素.

LinkedList.add(index, value)

  1. list 转为数组, 记得写array的大小

queue.toArray(new int[people.length][]

class Solution {
    
    
    public int[][] reconstructQueue(int[][] people) {
    
    
        Arrays.sort(people,
            (a, b) -> {
    
    
                if(a[0] == b[0]) return a[1] - b[1]; // 身高相同, k值升序排列
                return b[0] - a[0]; // 否则优先按身高降序排列
            }
        );

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

        for(int[] p : people){
    
    
            queue.add(p[1], p);
        }

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

猜你喜欢

转载自blog.csdn.net/weixin_45872648/article/details/131194668