一、题目
你正在参加一场比赛,给你两个正整数 initialEnergy 和 initialExperience 分别表示你的初始精力和初始经验。
另给你两个下标从 0 开始的整数数组 energy 和 experience,长度均为 n 。
你将会依次对上 n 个对手。第 i 个对手的精力和经验分别用 energy[i] 和 experience[i] 表示。当你对上对手时,需要在经验和精力上都 严格 超过对手才能击败他们,然后在可能的情况下继续对上下一个对手。
击败第 i 个对手会使你的经验增加 experience[i],但会将你的精力减少 energy[i] 。
在开始比赛前,你可以训练几个小时。每训练一个小时,你可以选择将增加经验增加 1 或者将精力增加 1 。
返回击败全部 n 个对手需要训练的 最少 小时数目。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/minimum-hours-of-training-to-win-a-competition/description/
二、C++解法
我的思路及代码
模拟
由于精力是每次都需要消耗的,所以我们可以统计一共需要的精力,然后让初始精力和共需要的精力进行比较,然后进行相应的逻辑处理。经验部分:我们可以采用模拟的方式,每次让当前的经验与所需的经验进行比较,若经验够则直接把这个怪的经验加上去,若不够则先进行训练(注意增加训练后的经验),然后再加上怪物对应的经验。返回所需的步骤次数即可。
class Solution {
public:
int minNumberOfHours(int initialEnergy, int initialExperience, vector<int>& energy, vector<int>& experience) {
int energySum=0;
int ans = 0;
for(int it:energy)
energySum+=it;
ans = initialEnergy>energySum?0:(energySum-initialEnergy)+1;
for(int i=0;i<experience.size();i++){
if(initialExperience<=experience[i]){
ans += experience[i]-initialExperience+1;
initialExperience += experience[i]-initialExperience+1;
}
initialExperience += experience[i];
}
return ans;
}
};
- 时间复杂度:O(n),需要遍历一遍 energy 和 experience 数组
- 空间复杂度:O(1),仅使用常数空间
官方参考代码
class Solution {
public:
int minNumberOfHours(int initialEnergy, int initialExperience, vector<int>& energy, vector<int>& experience) {
int sum = 0;
for (int e : energy) {
sum += e;
}
int trainingHours = initialEnergy > sum ? 0 : sum + 1 - initialEnergy;
for (int e : experience) {
if (initialExperience <= e) {
trainingHours += 1 + (e - initialExperience);
initialExperience = 2 * e + 1;
} else {
initialExperience += e;
}
}
return trainingHours;
}
};
- 时间复杂度:O(n),需要遍历一遍 energy 和 experience 数组
- 空间复杂度:O(1),仅使用常数空间