代码随想录算法训练营第三十四天|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;
}