题目来源
题目概述
小扣当前位于魔塔游戏第一层,共有 N 个房间,编号为 0 ~ N-1。每个房间的补血道具/怪物对于血量影响记于数组 nums,其中正数表示道具补血数值,即血量增加对应数值;负数表示怪物造成伤害值,即血量减少对应数值;0 表示房间对血量无影响。
小扣初始血量为 1,且无上限。假定小扣原计划按房间编号升序访问所有房间补血/打怪,为保证血量始终为正值,小扣需对房间访问顺序进行调整,每次仅能将一个怪物房间(负数的房间)调整至访问顺序末尾。请返回小扣最少需要调整几次,才能顺利访问所有房间。若调整顺序也无法访问完全部房间,请返回 -1。
思路分析
很显然,数值为正数的房间不需要移动,因为血量无上限。所以我们只需要考虑移动负数房间。 每次遇到负数我们可以放入一个临时缓冲区,并升序排序,这样可以保证每次需要移动通过房间时都把当前能遇到扣血最严重的房间移到后面。(这个临时缓冲区可以用优先级队列实现)
代码实现
java实现
java
public class Solution {
public int magicTower(int[] nums) {
long sum = 1;
int result = 0;
long temp = 0;
PriorityBlockingQueue<Integer> negativeQueue = new PriorityBlockingQueue<>(nums.length);
for (int data : nums) {
// 把扣血房间放入有限集队列排序
if (data < 0) {
negativeQueue.offer(data);
}
sum += data;
// 如果血量为空,把扣血最多的房间移到最后
if (sum < 1) {
int poll = negativeQueue.poll();
result++;
temp += poll;
sum -= poll;
}
}
return sum + temp > 0 ? result : -1;
}
}
c++实现
cpp
class Solution{
public:
int magicTower(vector<int>& nums) {
priority_queue<int, vector<int>, greater<int>> negative_queue;
long sum = 1;
int result = 0;
long temp = 0;
for (int data : nums) {
// 负数房间放入优先级队列排序
if (data < 0) {
negative_queue.push(data);
}
sum += data;
// 血量为负把扣血最严重的房间向后移
if (sum < 1) {
int top = negative_queue.top();
result++;
temp += top;
sum -= top;
negative_queue.pop();
}
}
return sum + temp > 0 ? result : -1;
}
}