代码随想录算法Day35 | 860.柠檬水找零 ,406.根据身高重建队列 ,452. 用最少数量的箭引爆气球

860.柠檬水找零

题目链接:860. 柠檬水找零 - 力扣(LeetCode)

思路

这道题有如下三种情况:

  • 情况一:账单是5,直接收下。
  • 情况二:账单是10,消耗一个5,增加一个10
  • 情况三:账单是20,优先消耗一个10和一个5,如果不够,再消耗三个5

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

 

代码

 1 class Solution {
 2     public boolean lemonadeChange(int[] bills) {
 3         int five = 0;
 4         int ten = 0;
 5 
 6         for (int i = 0; i < bills.length; i++) {
 7             if (bills[i] == 5) {
 8                 five++;
 9             } else if (bills[i] == 10) {
10                 five--;
11                 ten++;
12             } else if (bills[i] == 20) {
13                 if (ten > 0) {
14                     ten--;
15                     five--;
16                 } else {
17                     five -= 3;
18                 }
19             }
20             if (five < 0 || ten < 0) return false;
21         }
22         
23         return true;
24     }
25 }

 

406.根据身高重建队列

题目链接:406. 根据身高重建队列 - 力扣(LeetCode)

思路

本题有两个维度,h和k,看到这种题目一定要想如何确定一个维度,然后再按照另一个维度重新排列。

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

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

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

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

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

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

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

代码

 1 class Solution {
 2     public int[][] reconstructQueue(int[][] people) {
 3         // 身高从大到小排(身高相同k小的站前面)
 4         Arrays.sort(people, (a, b) -> {
 5             if (a[0] == b[0]) return a[1] - b[1];
 6             return b[0] - a[0];
 7         });
 8 
 9         LinkedList<int[]> que = new LinkedList<>();
10 
11         for (int[] p : people) {
12             que.add(p[1],p);
13         }
14 
15         return que.toArray(new int[people.length][]);
16     }
17 }

 

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

题目链接:452. 用最少数量的箭引爆气球 - 力扣(LeetCode)

思路

  • 首先按照气球的起点,对所有气球进行排序,为了让气球尽可能的重叠。
  • 从第二个气球开始,如果起点小于上一个气球的终点,说明有重叠,此时终点要更新为两个气球终点的最小值,方便下一次判断。
  • 如果起点大于上一个气球的终点,说明没有重叠,就要用新的箭了。 

局部最优:当气球出现重叠,一起射,所用弓箭最少。全局最优:把所有气球射爆所用弓箭最少。

注意:初始result时为1,因为如果poins不为空,那么至少是需要一个箭的。

代码

 1 /**
 2  * 时间复杂度 : O(NlogN)  排序需要 O(NlogN) 的复杂度
 3  * 空间复杂度 : O(logN) java所使用的内置函数用的是快速排序需要 logN 的空间
 4  */
 5 class Solution {
 6     public int findMinArrowShots(int[][] points) {
 7         // 根据气球直径的开始坐标从小到大排序
 8         // 使用Integer内置比较方法,不会溢出
 9         Arrays.sort(points, (a, b) -> Integer.compare(a[0], b[0]));
10 
11         int count = 1;  // points 不为空至少需要一支箭
12         for (int i = 1; i < points.length; i++) {
13             if (points[i][0] > points[i - 1][1]) {  // 气球i和气球i-1不挨着,注意这里不是>=
14                 count++; // 需要一支箭
15             } else {  // 气球i和气球i-1挨着
16                 points[i][1] = Math.min(points[i][1], points[i - 1][1]); // 更新重叠气球最小右边界
17             }
18         }
19         return count;
20     }
21 }

 

 

posted @ 2023-03-07 19:12  颜欢兮  阅读(28)  评论(0)    收藏  举报