Medium
题目描述
你正在玩一个视频游戏,需要保卫你的城市免受一群 n 个怪物的攻击。给你一个下标从 0 开始的整数数组 dist,其中 dist[i] 是第 i 个怪物与城市的初始距离(单位:千米)。
怪物以恒定的速度向城市移动。每个怪物的速度在整数数组 speed 中给出,其中 speed[i] 是第 i 个怪物的速度(单位:千米/分钟)。
你有一个武器,一旦完全充电,就可以消灭一个怪物。但是,武器需要一分钟才能充电。武器在最开始就是满电的。
当任何怪物到达你的城市时,你就输了。如果怪物在武器完全充电的那一刻到达城市,这也算作失败,游戏在你能够使用武器之前就结束了。
返回在你失败之前可以消灭的怪物的最大数量,如果你可以在所有怪物到达城市之前消灭它们,则返回 n。
示例 1:
输入:dist = [1,3,4], speed = [1,1,1]
输出:3
解释:
开始时,怪物的距离分别为 [1,3,4]。你消灭第一个怪物。
一分钟后,怪物的距离分别为 [X,2,3]。你消灭第二个怪物。
一分钟后,怪物的距离分别为 [X,X,2]。你消灭第三个怪物。
所有 3 个怪物都可以被消灭。
示例 2:
输入:dist = [1,1,2,3], speed = [1,1,1,1]
输出:1
解释:
开始时,怪物的距离分别为 [1,1,2,3]。你消灭第一个怪物。
一分钟后,怪物的距离分别为 [X,0,1,2],所以你失败了。
你只能消灭 1 个怪物。
示例 3:
输入:dist = [3,2,4], speed = [5,3,2]
输出:1
解释:
开始时,怪物的距离分别为 [3,2,4]。你消灭第一个怪物。
一分钟后,怪物的距离分别为 [X,0,2],所以你失败了。
你只能消灭 1 个怪物。
提示:
n == dist.length == speed.length1 <= n <= 10^51 <= dist[i], speed[i] <= 10^5
解题思路
这道题的核心思路是贪心算法。我们需要按照怪物到达城市的时间顺序来消灭它们。
首先计算每个怪物到达城市所需的时间:时间 = 距离 / 速度。注意这里要用上取整,因为怪物在任何时刻到达都算失败。
然后将所有怪物按照到达时间从小到大排序。接下来模拟消灭过程:
- 第0分钟可以消灭第一个怪物
- 第1分钟可以消灭第二个怪物
- …
- 第i分钟可以消灭第(i+1)个怪物
对于第i个要消灭的怪物,如果它的到达时间小于等于i,说明我们无法在它到达之前消灭它,游戏结束。
时间复杂度主要由排序决定,为O(n log n)。空间复杂度为O(n)用于存储到达时间。
这种贪心策略是最优的,因为我们总是优先消灭最早到达的怪物,这样能最大化我们的存活时间。
代码实现
class Solution {
public:
int eliminateMaximum(vector<int>& dist, vector<int>& speed) {
int n = dist.size();
vector<double> arrivalTime(n);
// 计算每个怪物的到达时间
for (int i = 0; i < n; i++) {
arrivalTime[i] = (double)dist[i] / speed[i];
}
// 按到达时间排序
sort(arrivalTime.begin(), arrivalTime.end());
// 贪心消灭怪物
for (int i = 0; i < n; i++) {
if (arrivalTime[i] <= i) {
return i;
}
}
return n;
}
};
class Solution:
def eliminateMaximum(self, dist: List[int], speed: List[int]) -> int:
n = len(dist)
# 计算每个怪物的到达时间
arrival_times = []
for i in range(n):
arrival_times.append(dist[i] / speed[i])
# 按到达时间排序
arrival_times.sort()
# 贪心消灭怪物
for i in range(n):
if arrival_times[i] <= i:
return i
return n
public class Solution {
public int EliminateMaximum(int[] dist, int[] speed) {
int n = dist.Length;
double[] arrivalTimes = new double[n];
// 计算每个怪物的到达时间
for (int i = 0; i < n; i++) {
arrivalTimes[i] = (double)dist[i] / speed[i];
}
// 按到达时间排序
Array.Sort(arrivalTimes);
// 贪心消灭怪物
for (int i = 0; i < n; i++) {
if (arrivalTimes[i] <= i) {
return i;
}
}
return n;
}
}
/**
* @param {number[]} dist
* @param {number[]} speed
* @return {number}
*/
var eliminateMaximum = function(dist, speed) {
const n = dist.length;
// 计算每个怪物的到达时间
const arrivalTimes = [];
for (let i = 0; i < n; i++) {
arrivalTimes.push(dist[i] / speed[i]);
}
// 按到达时间排序
arrivalTimes.sort((a, b) => a - b);
// 贪心消灭怪物
for (let i = 0; i < n; i++) {
if (arrivalTimes[i] <= i) {
return i;
}
}
return n;
};
复杂度分析
| 复杂度类型 | 复杂度 |
|---|---|
| 时间复杂度 | O(n log n) |
| 空间复杂度 | O(n) |
时间复杂度:O(n log n),主要由排序操作决定。 空间复杂度:O(n),用于存储每个怪物的到达时间。
相关题目
. Minimum Health to Beat Game (Medium)