跳到主要内容

1705.吃苹果的最大数目

· 阅读需 6 分钟

1、题干

有一棵特殊的苹果树,一连 n 天,每天都可以长出若干个苹果。在第 i 天,树上会长出 apples[i] 个苹果,这些苹果将会在 days[i] 天后(也就是说,第 i + days[i] 天时)腐烂,变得无法食用。也可能有那么几天,树上不会长出新的苹果,此时用 apples[i] == 0days[i] == 0 表示。

你打算每天 最多 吃一个苹果来保证营养均衡。注意,你可以在这 n 天之后继续吃苹果。

给你两个长度为 n 的整数数组 daysapples ,返回你可以吃掉的苹果的最大数目

 

示例 1:

输入:apples = [1,2,3,5,2], days = [3,2,1,4,2]
输出:7
解释:你可以吃掉 7 个苹果:
- 第一天,你吃掉第一天长出来的苹果。
- 第二天,你吃掉一个第二天长出来的苹果。
- 第三天,你吃掉一个第二天长出来的苹果。过了这一天,第三天长出来的苹果就已经腐烂了。
- 第四天到第七天,你吃的都是第四天长出来的苹果。

示例 2:

输入:apples = [3,0,0,0,0,2], days = [3,0,0,0,0,2]
输出:5
解释:你可以吃掉 5 个苹果:
- 第一天到第三天,你吃的都是第一天长出来的苹果。
- 第四天和第五天不吃苹果。
- 第六天和第七天,你吃的都是第六天长出来的苹果。

 

提示:

  • apples.length == n
  • days.length == n
  • 1 <= n <= 2 * 104
  • 0 <= apples[i], days[i] <= 2 * 104
  • 只有在 apples[i] = 0 时,days[i] = 0 才成立

又是优先队列,JS没有优先队列,又是被折磨的一天。。。 这道题跟课程表 III类似,可以看看我之前的题解,也是计数排序

2、执行结果

1.png

3、解题思路

  • 总体思路:使用贪心策略,在尚未腐烂的苹果中优先选择保质期最小的苹果。
  • 关键思路:基于计数排序求保质期最小的苹果,用数组存储苹果数量和保质期,数组的下标表示保质期、值表示该日期对应的苹果数量;找保质期最小的苹果只需要以上一个最小保质期为起点,遍历数组找到下标最小且值不为0的元素。
  • 时间复杂度:由于遍历的起点是上一个最小的保质期,因此总体实现出来的时间复杂度是 O(n)O(n),其中 nn 是最大保质期。

下面说明代码实现细节:

  • 计数排序容器记为freshArr,其下标表示保质期、值表示该保质期之前的苹果数量
  • 最小保质期记为minDay,用于记录有苹果剩余的最小保质期
  • 可以吃掉苹果的最大数量记为res,即最终结果
  • 接下来以最大保质期为限制逐天遍历,天数记为i
  • 在第i天时,如果i没有超过n且过期天数大于0(i < days.length && days[i] > 0),进行以下操作
    • 在计数排序容器freshArr中按保质期i + days[i] - 1累加苹果数量
    • 更新最小保质期minDay = Math.min(minDay, i + days[i] - 1)
  • 接下来只要找到有苹果剩余的最小保质期即可
    • 先确保最小保质期在今天之后,即minDay = Math.max(minDay, i)
    • 然后在计数排序容器freshArr中遍历,找到有苹果剩余的最小保质期
  • 接下来更新最终结果和计数排序容器freshArr中的苹果数量
    • 注意更新之前确定该保质期有苹果剩余,即if (freshArr[minDay]) res++, freshArr[minDay]--
  • 最后就得到可以吃掉苹果的最大数量res

4、代码

var eatenApples = function (apples, days) {
let res = 0, minDay = days[0] - 1;
const freshArr = new Array(days.length).fill(0);
for (let i = 0; i < freshArr.length; i++) {
if (i < days.length && days[i] > 0) {
freshArr[i + days[i] - 1] = (freshArr[i + days[i] - 1] || 0) + apples[i];
minDay = Math.min(minDay, i + days[i] - 1);
}
minDay = Math.max(minDay, i);
while (minDay < freshArr.length && !freshArr[minDay]) minDay++;
if (freshArr[minDay]) res++, freshArr[minDay]--;
}
return res;
};