摘要
本文主要介绍了LeetCode贪心算法的几个题目,包括860.柠檬水找零、406.根据身高重建队列、452. 用最少数量的箭引爆气球。
1、860.柠檬水找零
1.1 思路
-
局部最优:优先消耗10美元,因为5美元的找零用处更大,能多留着就多留着
-
3 种情况
- 账单是5: 5++
- 账单是10: 5--, 10++
- 账单是20: 10--,5--,20++; 5--,5--,20++
1.2 代码
public boolean lemonadeChange(int[] bills) {
int five = 0;
int ten = 0;
int twenty = 0;
for(int bill : bills) {
if(bill == 5) {
five++;
} else if(bill == 10) {
if(five > 0) {
five--;
ten++;
} else {
return false;
}
} else {
if(ten > 0 && five > 0) {
five--;
ten--;
twenty++;
} else if(five >= 3) {
five -= 3;
twenty++;
} else {
return false;
}
}
}
return true;
}
2、406.根据身高重建队列
2.1 思路
解题思路
- 先确定身高维度,然后再去确定k这个维度,最后得出题目要求的数列
- 按照身高排序之后,优先按身高高的people的k来插入,后序插入节点也不会影响前面已经插入的节点,最终按照k的规则完成了队列。
-
数组排序
-
Arrays.sort(people, (a, b) -> { if (a[0] == b[0]) return a[1] - b[1]; return b[0] - a[0]; });
-
-
LinkedList 按下标添加元素
-
LinkedList<int[]> que = new LinkedList<>(); for (int[] p : people) { que.add(p[1],p); }
-
-
集合转数组
-
que.toArray(new int[people.length][]);
-
插入过程
排序完的people: [[7,0], [7,1], [6,1], [5,0], [5,2],[4,4]]
插入的过程:
- 插入[7,0]:[[7,0]]
- 插入[7,1]:[[7,0],[7,1]]
- 插入[6,1]:[[7,0],[6,1],[7,1]]
- 插入[5,0]:[[5,0],[7,0],[6,1],[7,1]]
- 插入[5,2]:[[5,0],[7,0],[5,2],[6,1],[7,1]]
- 插入[4,4]:[[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]
此时就按照题目的要求完成了重新排列。
2.2 代码
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<>();
for(int[] p : people) {
queue.add(p[1], p);
}
return queue.toArray(new int[people.length][]);
}
3、452. 用最少数量的箭引爆气球
3.1 思路
- 如果当前气球的左边界大于前一个气球的右边界,说明一定要多加一个弓箭
- 反之则代表当前气球与前一个气球重叠,当前气球的右边界取当前气球和前一个气球有边界的最小值
3.2 代码
public int findMinArrowShots(int[][] points) {
Arrays.sort(points, (a, b) -> {
return 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]) {
count++;
} else {
points[i][1] = Math.min(points[i-1][1], points[i][1]);
}
}
return count;
}