消灭怪物的最大数量

标签: 贪心 数组 排序

难度: Medium

你正在玩一款电子游戏,在游戏中你需要保护城市免受怪物侵袭。给定一个 下标从 0 开始 且大小为 n 的整数数组 dist ,其中 dist[i] 是第 i 个怪物与城市的 初始距离(单位:千米)。

怪物以 恒定 的速度走向城市。每个怪物的速度都以一个长度为 n 的整数数组 speed 表示,其中 speed[i] 是第 i 个怪物的速度(单位:千米/分)。

你有一种武器,一旦充满电,就可以消灭 一个 怪物。但是,武器需要 一分钟 才能充电。武器在游戏开始时是充满电的状态,怪物从 第 0 分钟 时开始移动。

一旦任一怪物到达城市,你就输掉了这场游戏。如果某个怪物 恰好 在某一分钟开始时到达城市(距离表示为0),这也会被视为 输掉 游戏,在你可以使用武器之前,游戏就会结束。

返回在你输掉游戏前可以消灭的怪物的 最大 数量。如果你可以在所有怪物到达城市前将它们全部消灭,返回  n

示例 1:

输入:dist = [1,3,4], speed = [1,1,1]
输出:3
解释:
第 0 分钟开始时,怪物的距离是 [1,3,4],你消灭了第一个怪物。
第 1 分钟开始时,怪物的距离是 [X,2,3],你消灭了第二个怪物。
第 3 分钟开始时,怪物的距离是 [X,X,2],你消灭了第三个怪物。
所有 3 个怪物都可以被消灭。

示例 2:

输入:dist = [1,1,2,3], speed = [1,1,1,1]
输出:1
解释:
第 0 分钟开始时,怪物的距离是 [1,1,2,3],你消灭了第一个怪物。
第 1 分钟开始时,怪物的距离是 [X,0,1,2],所以你输掉了游戏。
你只能消灭 1 个怪物。

示例 3:

输入:dist = [3,2,4], speed = [5,3,2]
输出:1
解释:
第 0 分钟开始时,怪物的距离是 [3,2,4],你消灭了第一个怪物。
第 1 分钟开始时,怪物的距离是 [X,0,2],你输掉了游戏。 
你只能消灭 1 个怪物。

提示:

  • n == dist.length == speed.length
  • 1 <= n <= 105
  • 1 <= dist[i], speed[i] <= 105

Submission

运行时间: 99 ms

内存: 30.1 MB

class Solution:
    def eliminateMaximum(self, dist: List[int], speed: List[int]) -> int:
        arrivalTimes = sorted([(monsterDist - 1) // monsterSpeed + 1 for monsterDist, monsterSpeed in zip(dist, speed)])
        for attackTime, arrivalTime in enumerate(arrivalTimes):
            if arrivalTime <= attackTime:
                return attackTime
        return len(arrivalTimes)

Explain

本题解的核心思路是首先计算每个怪物到达城市的时间,然后根据到达时间进行排序。排序后的数组允许我们按顺序判断每个怪物是否可以在其到达之前被消灭。对于每个怪物,我们检查它的到达时间是否小于或等于我们攻击的时间(即第i分钟对应i号怪物)。如果某个怪物的到达时间小于或等于当前分钟数,游戏结束,返回已消灭的怪物数量。如果所有怪物都可以在到达之前被消灭,则返回怪物总数。

时间复杂度: O(n log n)

空间复杂度: O(n)

class Solution:
    def eliminateMaximum(self, dist: List[int], speed: List[int]) -> int:
        # 计算每个怪物到达城市的时间,并排序
        arrivalTimes = sorted([(monsterDist - 1) // monsterSpeed + 1 for monsterDist, monsterSpeed in zip(dist, speed)])
        # 遍历每个怪物,检查是否可以在其到达前被消灭
        for attackTime, arrivalTime in enumerate(arrivalTimes):
            # 若当前时间大于等于怪物到达时间,返回已消灭的怪物数
            if arrivalTime <= attackTime:
                return attackTime
        # 如果所有怪物都被消灭,返回怪物总数
        return len(arrivalTimes)

Explore

是的,这种方法在所有怪物速度相同的情况下仍然有效。因为怪物的到达时间主要由它们的初始距离决定,即使所有怪物的速度相同,它们的到达时间也可能不同,因为它们的初始距离可能不同。在这种情况下,到达时间仍然根据距离来计算并排序,消灭怪物的流程与速度差异无关,主要依赖于到达时间的顺序。因此,该方法在怪物速度相同的情况下依然可以正确工作。

如果所有怪物的初始距离都为0,那么根据题解的逻辑,每个怪物的到达时间会是1分钟(`(0 - 1) // speed + 1 = 1`)。这意味着所有怪物几乎同时在第1分钟到达城市。在这种极端情况下,玩家只能在第0分钟消灭一个怪物,随后在第1分钟时,由于所有剩余怪物同时到达,玩家无法继续消灭更多怪物。因此,题解在这种特殊情况下依然适用,但效果是只能消灭1个怪物,然后游戏结束。