题目链接
数据结构:小根堆
思路:每次往小根堆中插入一个Apple,按照Apple的剩余保质天数插入。每天只能吃小根堆的保质期最少的那个Apple,即堆顶的num-1即可。(思路简单,但是代码细节方面要很小心,可以尝试先自己实现一下思路)。这里将days进行了一些处理,即将days处理成,第几天过期,而不是最开始的还有几天过期,即days[i]表示第i天的苹果,第days[i]过期。
代码:
class Solution {
class Apple{
int num;
int day;
public Apple(int num, int day){
this.num = num;
this.day = day;
}
}
public int eatenApples(int[] apples, int[] days) {
PriorityQueue<Apple> priorityQueue = new PriorityQueue<>(new Comparator<Apple>() {
@Override
public int compare(Apple o1, Apple o2) {
return o1.day - o2.day;//按照保质期的天数
}
});//小根堆
for(int i = 0 ; i <days.length;i++){//处理days数组
days[i] = days[i] + i;
}//处理完毕后,days数组即表示第几天过期
int res = 0;//记录吃的苹果总数
int i = 0;//表示当前是第几天
for(;i <apples.length;i++){
while (!priorityQueue.isEmpty() && priorityQueue.peek().day<=i){
priorityQueue.poll();
}//将过期的苹果从堆中弹出,即(保质期小于等于当前的日期的)
if(apples[i]!=0){//长出来的苹果数目不为0才加入堆
priorityQueue.offer(new Apple(apples[i], days[i]));
}
if(priorityQueue.isEmpty()){//如果此时堆内已经是空了,说明没有苹果吃
continue;
}
if(priorityQueue.peek().num>1){//数量大于1的,吃掉一个
priorityQueue.peek().num -= 1;
}else{//等于1的直接弹出,相当于吃掉了
priorityQueue.poll();
}
res++;
}
i++;
while (!priorityQueue.isEmpty()){//n天过后继续吃
Apple apple = priorityQueue.poll();
int t = 0;
if(apple.day-i+1>=apple.num){//apple.day-i过期的期限距离当前天 还有几天, 即表示距离过期最多能吃的苹果数 比如 当前 第5天 第7天过期 应该是 7-5+1 最多还能吃3个
res += apple.num;//在apple.day-i内吃光 apple.num个苹果
t = i + apple.num-1;//一天吃一个苹果,吃了apple.num个苹果,所以用当前天加上apple.num天 -1是因为下面的i=t+1已经后移了一天
}else if(apple.day-i+1<apple.num){
res += (apple.day-i+1);//因为前面 t+1已经往后移动了一天,所以 这里需要 + 1
t = apple.day;//当前天是 i 吃了apple.day-i+1个苹果 i+ apple.day - i + 1 -1 -1也是因为下面的i=t+1往后移了一天
}
i=t+1;//往后移一天
while (!priorityQueue.isEmpty() && priorityQueue.peek().day<t){//将过期的苹果弹出
priorityQueue.poll();
}
}
return res;
}
}