随想录训练营Day35 | 贪心 - - 860.柠檬水找零, 406.根据身高重建队列
标签: LeetCode闯关记
860.柠檬水找零
思路: 有且仅有三种情况,针对bills[i] == 20,因为5元相比10元的找零更灵活,所以优先用10元,囤5元;
class Solution {
public boolean lemonadeChange(int[] bills) {
int five = 0;
int ten = 0;
for (int i = 0; i < bills.length; i++) {
if(bills[i] == 5){
five++;
}
if(bills[i] == 10){
if (five > 0){
ten++;
five--;
}else{
return false;
}
}
if(bills[i] == 20){
if(ten > 0 && five > 0){
ten--;
five--;
}else if (five >= 3){
five -= 3;
}else{
return false;
}
}
}
return true;
}
}
406.根据身高重建队列
毁灭吧
//彻底不太看得懂语法了
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];
});
LinkedList<int[]> queue = new LinkedList<>();
//段代码是将元素 p 插入到 LinkedList 的 p[1] 位置上,也就是说,如果 LinkedList 中已经有了 p[1] 个元素,则新加入的元素会放在这些元素之后。如果 p[1] 为 0,则表示这个人应该插入到队列的最前面。
//因为在排序后遍历 people 数组时,我们是按照身高从大到小的顺序遍历的,所以对于每个人,前面所有身高比它高(或相同)的人都已经被插入到了 LinkedList 中,而它们的 k 值肯定小于等于当前这个人的 k 值。因此,当前这个人插入时使用的索引应该是其 k 值,这样才能保证所有在它前面的人都已经被插入过了,而它自己插入时,只要考虑自己的 k 值即可。
for (int[] p : people) {
queue.add(p[1], p);
}
return queue.toArray(new int[people.length][]);
}
}
/*
1) 根据代码 que.add(p[1],p) 推测,这是一个将一个二元组(p)插入优先队列(que)中的操作。一般来说,优先队列需要支持以下两个操作:
add(priority, item):将一个元素 item 按照给定的优先级 priority 插入队列中;
pop():弹出队列中优先级最高的元素。
通常我们使用堆这种数据结构实现优先队列,其中 add(priority, item) 操作对应将元素插入堆中,pop() 操作则将堆顶元素取出,这样就保证了每次取出的元素都是当前堆中优先级最高的。具体来说,当我们调用 add(priority, item) 时,可以先将 item 和 priority 封装成一个节点,然后将该节点插入堆中即可。此时堆会根据节点中的优先级自动维护元素的位置。因此,我猜测在 que.add(p[1],p) 中,que 可能是一个堆,调用 add(p[1],p) 方法即向堆中插入一个元素 p,p[1] 则是 p 的优先级。
2) new int[people.length][] :
这是一个Java中创建二维数组的语法。其中people.length表示一维数组的长度,也即第一维的大小;而后面的方括号[]则表示第二维的大小不确定,需要在之后给定。
换句话说,这行代码创建了一个二维整型数组,其中第一维的大小为people数组的长度,第二维的大小暂时未确定,需要在之后动态地进行初始化。
*/
time:1h10min
452. 用最少数量的箭引爆气球
key:
- 思路很简单,即找到重叠气球则不射箭,不是重叠气球则射箭
- 模拟射箭的过程,不需要remove数组中的元素,只需要统计箭的个数
- 初始话箭的count为1,因为points.length >=1,之后的for循环中,从第二个气球(下标为1)开始遍历,找到了重叠气球不用count++,但是需要更新最小右边界,为后续的比较更新points[i-1][1];
class Solution {
public int findMinArrowShots(int[][] points) {
Arrays.sort(points,(a,b) -> Integer.compare(a[0],b[0]));
int count = 1;
for (int i = 1; i < points.length; i++) {
if(points[i][0] <= points[i-1][1]){//要是气球i和气球i-1挨着,更新重叠气球最小右边界
points[i][1] = Math.min(points[i-1][1], points[i][1]);
}else{//气球i和气球i-1不挨着
count++;// 需要一支箭
}
}
return count;
}
}