力扣1921——消灭怪物的最大数量(贪心+哈希表)

题目(中等)

你正在玩一款电子游戏,在游戏中你需要保护城市免受怪物侵袭。给你一个 下标从 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],你没有消灭任何怪物。
第 2 分钟开始时,怪物的距离是 [X,1,2],你消灭了第二个怪物。
第 3 分钟开始时,怪物的距离是 [X,X,1],你消灭了第三个怪物。
所有 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 <= 10^5
1 <= dist[i], speed[i] <= 10^5

思路

为了贪心的保护城市,火力不要停,尽可能多的消灭怪兽。
首先统计每个怪兽的达到时间,进行向上取整,比如举例4,速度3,该怪兽会在2时刻达到,向上取整为(a-1)/b + 1;
统计每个达到时间,有多少怪兽会到达,用哈希表计数,并对达到时刻进行去重排序;
之后就开始模拟,从0时刻开始,如果剩余时间大于怪兽数量,就消灭这些怪兽,并消耗对应时间,更新答案;
如果时间来不及,结束前先消灭能消灭的怪兽,更新答案后结束游戏。

代码

class Solution {
public:
    int eliminateMaximum(vector<int>& dist, vector<int>& speed) {
        int n = dist.size();
        int ans = 0;
        int time = 0;
        vector<int> arrive(n);  //每个怪物到达时间
        for(int i = 0; i < n ; i++) arrive[i] = (dist[i] - 1) / speed[i] + 1;   //向上取整
        unordered_map<int, int> hash;   //统计每个时刻有多少怪物会来
        for(auto x : arrive) hash[x]++;
        vector<int> arr_time;     //去重后到达时间,排序
        for(auto x : hash) arr_time.push_back(x.first);
        sort(arr_time.begin(), arr_time.end());
        for(auto x : arr_time) {
            if(x - time >= hash[x]) {
                time += hash[x];
                ans += hash[x];
            }
            else {
                ans += x - time;
                break;
            }
        }
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值