题目来源:https://leetcode-cn.com/problems/maximum-number-of-eaten-apples/
大致题意:
给一个苹果数组表示每天可以产出的苹果数量,再给一个保质期数组表示当天产出苹果的保质期。假设每天最多吃一个苹果,最多可以有多少天吃到苹果
思路
首先需要明了,最后一天的产出的苹果如果保质期够长,数量够多,哪怕接下来不产出苹果,之后的几天仍然可以吃最后一天多余的还能吃的苹果
如果想吃的天数够多,那么就需要尽可能先吃保质期短的,就是尽可能先吃快要过期的
显然就是贪心
于是可以用优先队列存下每天产出的苹果和对应的还能吃的截止日期,按照截止日期升序排序
贪心 + 优先队列
- 如果当前还能产出苹果,将苹果数量和对应的截止日期存入队列
- 从当前剩余的苹果中选出快要过期的吃
代码:
public int eatenApples(int[] apples, int[] days) {
PriorityQueue<int[]> queue = new PriorityQueue<>((a, b) -> a[1] - b[1]);
int day = 0; // 日期
int n = apples.length;
int ans = 0; // 吃的苹果数量
// 当还可以产出苹果或者还有能吃的苹果时继续循环
while (day < n || !queue.isEmpty()) {
// 如果还有新成熟的苹果,加入队列
if (day < n) {
// 腐烂的日期
int rotDay = days[day] + day;
int num = apples[day];
queue.offer(new int[]{num, rotDay - 1});
}
// 把腐烂的苹果去掉
while (!queue.isEmpty() && queue.peek()[1] < day) {
queue.poll();
}
// 如果还有能吃的苹果
if (!queue.isEmpty()) {
int[] apple = queue.poll();
// 如果这包苹果数量大于 1,那么吃完重新放入队列
if (apple[0] > 1 && apple[1] > day) {
queue.offer(new int[]{apple[0] - 1, apple[1]});
}
// 只有当前苹果数量大于 0 时,才能吃
if (apple[0] > 0) {
ans++;
}
}
day++;
}
return ans;
}