反悔贪心
遍历时,贪心选择权重最高的值,同时将没有选择的信息保留(优先队列),以便反悔替换
有时存在两个维度,按其中一个维度排序,另一个维度反悔贪心
1. 魔塔游戏
反悔贪心
class Solution {
public:
int magicTower(vector<int>& nums) {
long sum = 0;
for(int n:nums)
sum+=n;
if(sum<0) return -1;
int times = 0; long presum = 1;//初始血量
priority_queue<int> q;
for(int i=0;i<nums.size();i++){
if(nums[i]<0)//如果是小怪,暂存起来
q.push(-nums[i]);
presum+=nums[i];//打小怪
while(presum<1){//打不过选择收益最大的小怪跳过,也可以用if
presum+=q.top();
q.pop();
times++;
}
}
return times;
}
};
2. 将数组和减半的最少操作数
反悔贪心
class Solution {
public:
int halveArray(vector<int>& nums) {
sort(nums.begin(),nums.end(),greater<int>());
double sum = accumulate(nums.begin(),nums.end(),0ll)*0.5;
priority_queue<double> q;
double sub = 0;
for(int i=0;i<nums.size();i++){
q.push((double)nums[i]);
sub += q.top()/2;
q.push(q.top()/2);
q.pop();
if(sub>=sum) return i+1;
}
return 0;
}
};
3. 可以到达的最远建筑
反悔贪心
class Solution {
public:
int furthestBuilding(vector<int>& heights, int bricks, int ladders) {
int n = heights.size();
priority_queue<int, vector<int>, greater<int>> q;
int sum = 0;
for (int i = 1; i < n; ++i) {//贪心选择
int deltaH = heights[i] - heights[i - 1];
if (deltaH <= 0) continue;//不需要梯子和砖
q.push(deltaH);//优先使用梯子,暂存以便反悔
//梯子不够用,反悔前面的一个使用砖头
if (q.size() > ladders) {
sum += q.top();
q.pop();
}
if (sum > bricks) return i - 1;
}
return n - 1;
}
};