Maximum Number of Eaten Apples
Problem
There is a special kind of apple tree that grows apples every day for n
days. On the ith day, the tree grows apples[i] apples that will rot after
days[i] days, that is on day i + days[i] the apples will be rotten and cannot be eaten. On some days, the apple tree does not grow any apples, which are denoted by apples[i] == 0 and days[i] == 0.
You decided to eat at most one apple a day (to keep the doctors away).
Note that you can keep eating after the first n days.
Given two integer arrays days and apples of length n, return the maximum number of apples you can eat.
Examples
Example 1
Input: apples = [1,2,3,5,2], days = [3,2,1,4,2]
Output: 7
Explanation: You can eat 7 apples:
- On the first day, you eat an apple that grew on the first day.
- On the second day, you eat an apple that grew on the second day.
- On the third day, you eat an apple that grew on the second day. After this day, the apples that grew on the third day rot.
- On the fourth to the seventh days, you eat apples that grew on the fourth day.
Example 2
Input: apples = [3,0,0,0,0,2], days = [3,0,0,0,0,2]
Output: 5
Explanation: You can eat 5 apples:
- On the first to the third day you eat apples that grew on the first day.
- Do nothing on the fouth and fifth days.
- On the sixth and seventh days you eat apples that grew on the sixth day.
Constraints
n == apples.length == days.length1 <= n <= 2 * 10^40 <= apples[i], days[i] <= 2 * 10^4days[i] = 0if and only ifapples[i] = 0.
Solution
Method 1 – Greedy + Min Heap
Intuition
To maximize the number of apples eaten, always eat the apple that will rot the soonest. Use a min-heap to keep track of apple batches by their expiration day, and eat one apple per day from the batch that expires first.
Approach
- For each day, if apples grow, add a batch
(expire_day, count)to the min-heap. - Remove any batches from the heap that have expired or have no apples left.
- If the heap is not empty, eat one apple from the batch with the earliest expiration.
- Continue this process until all apples are processed and the heap is empty.
- Count the total apples eaten.
Code
C++
class Solution {
public:
int eatenApples(vector<int>& apples, vector<int>& days) {
int n = apples.size(), ans = 0, i = 0;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;
while (i < n || !pq.empty()) {
if (i < n && apples[i] > 0) {
pq.emplace(i + days[i], apples[i]);
}
while (!pq.empty() && (pq.top().first <= i || pq.top().second == 0)) pq.pop();
if (!pq.empty()) {
auto p = pq.top(); pq.pop();
ans++;
if (--p.second > 0) pq.push(p);
}
i++;
}
return ans;
}
};
Go
import "container/heap"
type apple struct{expire, count int}
type minHeap []apple
func (h minHeap) Len() int { return len(h) }
func (h minHeap) Less(i, j int) bool { return h[i].expire < h[j].expire }
func (h minHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *minHeap) Push(x interface{}) { *h = append(*h, x.(apple)) }
func (h *minHeap) Pop() interface{} { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v }
func eatenApples(apples, days []int) int {
n, ans, i := len(apples), 0, 0
h := &minHeap{}
heap.Init(h)
for i < n || h.Len() > 0 {
if i < n && apples[i] > 0 {
heap.Push(h, apple{i + days[i], apples[i]})
}
for h.Len() > 0 && ((*h)[0].expire <= i || (*h)[0].count == 0) {
heap.Pop(h)
}
if h.Len() > 0 {
(*h)[0].count--
ans++
if (*h)[0].count == 0 {
heap.Pop(h)
}
}
i++
}
return ans
}
Java
import java.util.*;
class Solution {
public int eatenApples(int[] apples, int[] days) {
int n = apples.length, ans = 0, i = 0;
PriorityQueue<int[]> pq = new PriorityQueue<>(Comparator.comparingInt(a -> a[0]));
while (i < n || !pq.isEmpty()) {
if (i < n && apples[i] > 0) {
pq.offer(new int[]{i + days[i], apples[i]});
}
while (!pq.isEmpty() && (pq.peek()[0] <= i || pq.peek()[1] == 0)) pq.poll();
if (!pq.isEmpty()) {
int[] p = pq.poll();
ans++;
if (--p[1] > 0) pq.offer(p);
}
i++;
}
return ans;
}
}
Kotlin
import java.util.PriorityQueue
class Solution {
fun eatenApples(apples: IntArray, days: IntArray): Int {
val n = apples.size
var ans = 0
var i = 0
val pq = PriorityQueue(compareBy<Pair<Int, Int>> { it.first })
while (i < n || pq.isNotEmpty()) {
if (i < n && apples[i] > 0) {
pq.add(Pair(i + days[i], apples[i]))
}
while (pq.isNotEmpty() && (pq.peek().first <= i || pq.peek().second == 0)) pq.poll()
if (pq.isNotEmpty()) {
val p = pq.poll()
ans++
if (p.second - 1 > 0) pq.add(Pair(p.first, p.second - 1))
}
i++
}
return ans
}
}
Python
import heapq
class Solution:
def eatenApples(self, apples: list[int], days: list[int]) -> int:
n, ans, i = len(apples), 0, 0
heap = []
while i < n or heap:
if i < n and apples[i] > 0:
heapq.heappush(heap, (i + days[i], apples[i]))
while heap and (heap[0][0] <= i or heap[0][1] == 0):
heapq.heappop(heap)
if heap:
expire, count = heapq.heappop(heap)
ans += 1
if count - 1 > 0:
heapq.heappush(heap, (expire, count - 1))
i += 1
return ans
Rust
use std::collections::BinaryHeap;
use std::cmp::Reverse;
impl Solution {
pub fn eaten_apples(apples: Vec<i32>, days: Vec<i32>) -> i32 {
use std::collections::BinaryHeap;
let n = apples.len();
let mut ans = 0;
let mut i = 0;
let mut heap = BinaryHeap::new();
while i < n || !heap.is_empty() {
if i < n && apples[i] > 0 {
heap.push(Reverse((i as i32 + days[i], apples[i])));
}
while let Some(&Reverse((expire, count))) = heap.peek() {
if expire <= i as i32 || count == 0 {
heap.pop();
} else {
break;
}
}
if let Some(Reverse((expire, mut count))) = heap.pop() {
ans += 1;
count -= 1;
if count > 0 {
heap.push(Reverse((expire, count)));
}
}
i += 1;
}
ans
}
}
TypeScript
class Solution {
eatenApples(apples: number[], days: number[]): number {
const n = apples.length;
let ans = 0, i = 0;
const heap: [number, number][] = [];
const push = (item: [number, number]) => {
heap.push(item);
heap.sort((a, b) => a[0] - b[0]);
};
while (i < n || heap.length) {
if (i < n && apples[i] > 0) push([i + days[i], apples[i]]);
while (heap.length && (heap[0][0] <= i || heap[0][1] === 0)) heap.shift();
if (heap.length) {
let [expire, count] = heap.shift()!;
ans++;
if (count - 1 > 0) push([expire, count - 1]);
}
i++;
}
return ans;
}
}
Complexity
- ⏰ Time complexity:
O(n log n), wherenis the number of days, due to heap operations for each day. - 🧺 Space complexity:
O(n), for the heap storing apple batches.