首页 > 后端开发 > php教程 > 从最富有的一堆礼物中拿走

从最富有的一堆礼物中拿走

Barbara Streisand
发布: 2025-01-01 04:30:09
原创
311 人浏览过

Take Gifts From the Richest Pile

2558。从最富有的一堆礼物中拿走

难度:简单

主题:数组、堆(优先级队列)、模拟

您将获得一个整数数组礼物,表示各堆礼物的数量。每一秒,您都会执行以下操作:

  • 选择礼物数量最多的那堆。
  • 如果礼物数量超过上限,则选择任意一个。
  • 留下一堆礼物数量的平方根的下限。剩下的礼物拿走吧。

返回k秒后剩余的礼物数量.

示例1:

  • 输入: 礼物 = [25,64,9,4,100], k = 4
  • 输出: 29
  • 说明:礼物的领取方式如下:
    • 第一秒,最后一堆被选中,留下10份礼物。
    • 然后选择第二堆,留下8份礼物。
    • 选择完第一堆后,留下 5 份礼物。
    • 最后,最后一堆被再次选出,剩下3份礼物。
    • 最终剩余礼物数量为[5,8,9,4,3],所以剩余礼物总数为29。

示例2:

  • 输入: 礼物 = [1,1,1,1], k = 4
  • 输出: 4
  • 说明:这种情况下,无论你选择哪一堆,每堆都必须留下 1 件礼物。
    • 也就是说,你不能带走任何东西。
    • 所以,剩下的礼物总数是 4。

约束:

  • 1 3
  • 1 9
  • 1 3

提示:

  1. 如何跟踪阵列中最大的礼物
  2. 求数字平方根的有效方法是什么?
  3. 你能不断累加礼物的价值,同时确保它们按一定顺序排列吗?
  4. 我们可以在这里使用优先级队列或堆吗?

解决方案:

我们可以利用最大堆(优先级队列),因为我们需要反复挑选礼物数量最多的堆。最大堆将使我们能够在恒定的时间内有效地访问最大的堆,并在从堆中取出礼物后更新堆。

方法:

  1. 使用最大堆:

    • 由于我们需要重复获取最大数量礼物的堆,因此最大堆(优先级队列)是理想的选择。在 PHP 中,我们可以使用 SplPriorityQueue,它是一个优先级队列,默认情况下用作最大堆。
    • 为了模拟最大堆,我们将插入礼物数量作为负值,因为 SplPriorityQueue 默认是最小堆。通过插入负值,最小的负值将代表最大的原始数。
  2. 每秒处理:

    • 每一秒,从堆中弹出最多数量的礼物。
    • 拿走除该堆礼物数量平方根的下限以外的所有礼物。
    • 将修改后的堆推回到堆中。
  3. 终止:

    • 我们在 k 秒后或处理完所有秒后停止。

让我们用 PHP 实现这个解决方案:2558。从最富有的一堆礼物中拿走

<?php
/**
 * @param Integer[] $gifts
 * @param Integer $k
 * @return Integer
 */
function pickGifts($gifts, $k) {
    ...
    ...
    ...
    /**
     * go to ./solution.php
     */
}

// Example usage:
$gifts1 = [25, 64, 9, 4, 100];
$k1 = 4;
echo pickGifts($gifts1, $k1) . "\n"; // Output: 29

$gifts2 = [1, 1, 1, 1];
$k2 = 4;
echo pickGifts($gifts2, $k2) . "\n"; // Output: 4
?>
登录后复制
登录后复制

解释:

  1. 堆初始化:

    • SplPriorityQueue 用于模拟最大堆。 insert 方法允许我们优先将元素推入堆中。
  2. 处理最大的一堆

    • 对于 k 次迭代,使用 extract 提取最大的一堆。
    • 留下的礼物数量计算为当前最大堆的平方根的下限,使用floor(sqrt(...))。
    • 减少的堆被重新插入到堆中。
  3. 总结剩余礼物

    • 经过k次运算后,将堆中的所有元素提取出来并求和,得到剩余礼物的总数。
  4. 边缘情况

    • 如果礼物为空,则结果为0。
    • 如果 k 大于可能的操作数,算法会妥善处理它。

时间复杂度:

  • 堆操作(插入和提取):每个堆操作(插入和提取)需要 O(log n),其中 n 是堆的数量。
  • 循环执行 k 个操作:我们执行 k 个操作,每个操作都涉及堆提取和插入,都需要 O(log n).

因此,总时间复杂度为 O(k log n),其中 n 是堆的数量,k 是秒数。

演练示例:

输入:

<?php
/**
 * @param Integer[] $gifts
 * @param Integer $k
 * @return Integer
 */
function pickGifts($gifts, $k) {
    ...
    ...
    ...
    /**
     * go to ./solution.php
     */
}

// Example usage:
$gifts1 = [25, 64, 9, 4, 100];
$k1 = 4;
echo pickGifts($gifts1, $k1) . "\n"; // Output: 29

$gifts2 = [1, 1, 1, 1];
$k2 = 4;
echo pickGifts($gifts2, $k2) . "\n"; // Output: 4
?>
登录后复制
登录后复制
  1. 最初,优先级队列有以下堆:[25, 64, 9, 4, 100]。
  2. 1秒后:选择100,留下10。剩余礼物为:[25, 64, 9, 4, 10]。
  3. 2秒后:选择64,留下8。剩余礼物为:[25,8,9,4,10]。
  4. 3秒后:选择25,留下5。剩余礼物为:[5,8,9,4,10]。
  5. 4秒后:选择10个,留下3个。剩下的礼物是:[5,8,9,4,3]。

剩余礼物的总和为5 8 9 4 3 = 29

这种方法使用最大堆有效地解决了问题,并且在给定的约束下表现良好。

联系链接

如果您发现本系列有帮助,请考虑在 GitHub 上给 存储库 一个星号或在您最喜欢的社交网络上分享该帖子?。您的支持对我来说意义重大!

如果您想要更多类似的有用内容,请随时关注我:

  • 领英
  • GitHub

以上是从最富有的一堆礼物中拿走的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板