代码随想录算法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 }

浙公网安备 33010602011771号