视频讲解:
贪心算法,看上去复杂,其实逻辑都是固定的!LeetCode:860.柠檬水找零_哔哩哔哩_bilibili
860.柠檬水找零
思路:没有特别明确的贪心思想,可能涉及到贪心的思想就是在处理找零15元时,优先消耗10元的纸币,没有10元的,但消耗3张5元的。本题的关键就是统计5元,10元纸币的数量,虽然是有必要统计一下总共的利润来评估是否还有钱来找零,但是所有的找零都是花费的5元和10元,所以20元的无需统计,那么总利润统计也就没有意义,只要剩余的5元和10元纸币的数量可以应付所有找零,那么本题就可以返回true;反之返回一个false。
// 时间复杂度O(n)
// 空间复杂度O(1)
class Solution {
public boolean lemonadeChange(int[] bills) {
// 思路和昨天的加油站的第二种解法非常的类似
// 分别用于计数5元,10元,20元
int five = 0;
int ten = 0;
for(int i=0; i<bills.length; i++){
// 首先收取顾客的钱
if(bills[i] == 5)
five++;
else if(bills[i] == 10)
ten++;
// 计算当前的找零
int change = bills[i] - 5;
if(change == 0)
continue;
else if(change==5 && five>0)
five--;
else if(change==15 && ten>0 && five>0){
// 找零15的时候应当优先消耗10元,这就是贪心的一部分
five--;
ten--;
}
else if(change == 15 && five>=3)
five -= 3;
else
return false;
}
return true;
}
}
406. 根据身高重建队列
思路:参考 代码随想录 的思路解出。明确涉及两个维度需要控制的题目时,优先确定一个维度然后再去操作另一个维度,即优先将一个维度的关系确定,然后再此基础上再去确定另一个维度。与此相同思路的题目中分发糖果,参考的左右两个相邻的位置,因此也是两个维度。
// 时间复杂度O(nlogn),是Arrays.sort()的时间复杂度
// 空间复杂度O(n)
class Solution {
public int[][] reconstructQueue(int[][] people) {
Arrays.sort(people, (a,b)->{
if(a[0] == b[0]) return a[1]-b[1];
return b[0]-a[0];
});
List<int[]> que = new ArrayList<>();
// 现在完成排序的people数组是h按照从大到小,k在h相同时才会使用到作为从小到大,用来维护之后进行赋值时的索引正确性
// 而可以直接插入的缘故就是,将一个小的数加入到他的前面去不影响之前的数的h和k,因为之前的数的h都比当前数的h来的大
for(int[] p:people)
que.add(p[1], p);
return que.toArray(new int[people.length][]);
}
}
452. 用最少数量的箭引爆气球
思路:新的一种类型的题目——“重叠区间”。首先自己实现了这道题的题解,认为重叠区间类型题目的解题就是合并存在交集的区间,然后统计最终还剩下几个相互独立的区间;而贪心的策略就是如果可以时间效率最小的情况下完成区间的合并。在这个思路和两个维度的确定一个维度比较像,优先确定所有区间的下限的关系,然后再判断区间彼此之间是否存在交集,存在交集即融合即可。
// 时间复杂度O(nlogn),排序耗时
// 空间复杂度O(n)
class Solution {
public int findMinArrowShots(int[][] points) {
// 尝试先做,思路是计算重合的区间个数
if(points.length == 1)
return 1;
// 按照起始的位置从小到大排列,注意这里需要自己写大小判断,然后返回负数还是正数,因为采用a[0]-b[0]的方式会存在数值越界的情况
Arrays.sort(points, (a,b)->{
if(a[0] < b[0]) return -1;
if(a[0] == b[0]) return 0;
return 1;
});
List<int[]> scopes = new ArrayList<>();
int[] cur = points[0];
scopes.add(points[0]);
// cur保存当前区间下限最小的,开始进行区间的合并
for(int i=1; i<points.length; i++){
if( (long)points[i][0] > (long)cur[1] ){
scopes.add(points[i]);
cur = points[i];
}
else{
cur[0] = Math.max(cur[0], points[i][0]);
cur[1] = Math.min(cur[1], points[i][1]);
}
}
return scopes.size();
}
}