860.柠檬水找零
思路:先用元素全为5的数组去减bills数组,得到找零数组,之后遍历bills数组,去把找零数组元素全部变为零,怎么填补我想不出来
尝试(部分AC)
class Solution {
public boolean lemonadeChange(int[] bills) {
Arrays.sort(bills);
int[] gap = new int[bills.length];
for(int i =0; i<bills.length; i++){
gap[i] = 5 - bills[i];
}
int result = 0;
int index = 0;
for(int i : gap){
if(i<0){
while(result + i < 0 && index < bills.length){
result += bills[index];
index++;
}
if(result + i > 0){
return false;
}
}
}
return true;
}
}
答案
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++;
} else if (bills[i] == 10) {
five--;
ten++;
} else if (bills[i] == 20) {
if (ten > 0) {
ten--;
five--;
} else {
five -= 3;
}
}
if (five < 0 || ten < 0) return false;
}
return true;
}
}
小结
- 简单粗暴的处理逻辑,直接把所有情况都列出来
- 这是单步操作,遍历bills数组,挨个判断处理
406.根据身高重建队列
题目:406. 根据身高重建队列 - 力扣(LeetCode)
思路:我想不到遍历要怎么处理
答案
class Solution {
public int[][] reconstructQueue(int[][] people) {
// 身高从大到小排(身高相同k小的站前面)
Arrays.sort(people, (a, b) -> {
if (a[0] == b[0]) return a[1] - b[1]; // a - b 是升序排列,故在a[0] == b[0]的狀況下,會根據k值升序排列
return b[0] - a[0]; //b - a 是降序排列,在a[0] != b[0],的狀況會根據h值降序排列
});
LinkedList<int[]> que = new LinkedList<>();
for (int[] p : people) {
que.add(p[1],p); //Linkedlist.add(index, value),會將value插入到指定index裡。
}
return que.toArray(new int[people.length][]);
}
}
小结
- 需要考虑两个维度的问题,要先确定一个,不要身高和个数同时考虑
- que.add(p[1],p);】这个队列函数很关键!可以插入到指定的【p[1]】下标处
- 身高从大到小排,同身高的k小的排前面,之后用队列的插入函数
- people[i] = [hi, ki] ,【ki】表示了有几个元素比当前元素大,所以先身高从大到小排,后面插入的时候,直接根据【ki】的信息,就能找到插入的位置,因为前面的元素都是比自己要大的,遍历的时候就是从大到小遍历,而且插入小身高的元素,并不会影响大身高的元素,秒!
- Comparator是一个用于比较大小的函数式接口,简单来说【只要记住,返回a - b,就是升序排序,返回b - a就是降序排列】
Arrays.sort(people, (a, b) -> {
if (a[0] == b[0]) return a[1] - b[1]; // a - b 是升序排列
return b[0] - a[0]; //b - a 是降序排列
});
452.用最少数量的箭引爆气球
题目:452. 用最少数量的箭引爆气球 - 力扣(LeetCode)
思路:找重叠区间,逐个扫描区间,把区间范围内的元素加1,全部元素扫描完成之后,就知道了重叠区间,把带有重叠区间信息的数组排序一遍,取出最大的几个元素,直到加起来数字超过气球个数,每加一个数就相当于射出一箭,最后返回这个数
尝试(部分AC)
class Solution {
public int findMinArrowShots(int[][] points) {
// 升序排列,根据区间的结束时间进行排序
Arrays.sort(points, (a, b) -> a[1] - b[1]);
// 初始化record数组,长度为最后一个区间的结束时间
int maxLength = points[points.length - 1][1];
int[] record = new int[maxLength + 1]; // 需要+1因为数组索引从0开始
// 遍历points数组的元素,将每个元素当作区间
for (int[] p : points) {
// 遍历区间的开始时间和结束时间
for (int i = p[0]; i <= p[1]; i++) {
// 给record数组对应的区间数字加上1
record[i]++;
}
}
Arrays.sort(record);
int result = 0;
int count = 0;
int index = record.length -1;
while(result < points.length){
result += record[index];
index--;
count++;
}
return count;
}
}
答案
class Solution {
public int findMinArrowShots(int[][] points) {
// 根据气球直径的开始坐标从小到大排序
// 使用Integer内置比较方法,不会溢出
Arrays.sort(points, (a, b) -> Integer.compare(a[0], b[0]));
int count = 1; // points 不为空至少需要一支箭
for (int i = 1; i < points.length; i++) {
if (points[i][0] > points[i - 1][1]) { // 气球i和气球i-1不挨着,注意这里不是>=
count++; // 需要一支箭
} else { // 气球i和气球i-1挨着,区间有重叠,那就合并区间
points[i][1] = Math.min(points[i][1], points[i - 1][1]); // 更新重叠气球最小右边界
}
}
return count;
}
}
小结
- 我的方法不行,因为数字范围很大的时候,就要建立一个很大的数组,会超出内存
- 卡尔的思路就是,先把元素从小到大排序,然后相邻的区间逐个合并,不能合并时,就射出一支箭
- 要用【Arrays.sort(points, (a, b) -> Integer.compare(a[0], b[0]));】才不会溢出