贪心算法 part 03
贪心算法
●1005.K次取反后最大化的数组和
● 134. 加油站
● 135. 分发糖果
1005.K次取反后最大化的数组和
法1:贪心
static bool cmp(int a,int b){
if (abs(a) >abs(b))
return true;
return false;
}
int largestSumAfterKNegations(vector<int>& nums, int k) {
sort(nums.begin(),nums.end(),cmp);
for (int i = 0; i < nums.size(); ++i) {
if (nums[i] < 0 && k > 0){
k--;
nums[i] *= -1;
}
}
int ans = 0;
if (k % 2 == 1) nums[nums.size() - 1] *= -1;
for (const auto &item: nums)
ans += item;
return ans;
}
134. 加油站
134. 加油站
法1:贪心
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
//暴力模拟
//贪心算法
/**
* 情况一:如果gas的总和小于cost总和,
* 那么无论从哪里出发,一定是跑不了一圈的
情况二:rest[i] = gas[i]-cost[i]为一天剩下的油,
i从0开始计算累加到最后一站,如果累加没有出现负数,
说明从0出发,油就没有断过,那么0就是起点。
情况三:如果累加的最小值是负数,汽车就要从非0节点出发,从后向前,
看哪个节点能把这个负数填平,能把这个负数填平的节点就是出发节点。
*/
int cur_sum = 0;
// rest[i] = gas[i]-cost[i]
int min = INT_MAX; // 从起点出发,油箱里的油量最小值
for (int i = 0; i < cost.size(); ++i) {
int rest = gas[i] - cost[i];
cur_sum += rest;
if (min >= cur_sum)
min = cur_sum;
}
if (cur_sum < 0)return -1;
for (int i = gas.size(); i >= 0 ; --i) {
int rest = gas[i] - cost[i];
min += rest;
if (min >= 0)
return i;
}
return -1;
}
135. 分发糖果
法1:贪心
int candy(vector<int>& ratings) {
vector<int> candies(ratings.size(),1);
int sum = 0;
for (int i = 1; i < ratings.size(); ++i) {
if (ratings[i] > ratings[i - 1])
candies[i] = candies[i - 1] + 1;
}
/**
* 所以确定左孩子大于右孩子的情况一定要从后向前遍历!
如果 ratings[i] > ratings[i + 1],此时candyVec[i](
第i个小孩的糖果数量)就有两个选择了,
一个是candyVec[i + 1] + 1(从右边这个加1得到的糖果数量),
一个是candyVec[i](之前比较右孩子大于左孩子得到的糖果数量)。
*/
for (int i = ratings.size()-1; i >= 1; i--) {
if (ratings[i - 1] > ratings[i] )
candies[i - 1] = max(candies[i - 1],candies[i] + 1);
}
for (const auto &item: candies)
sum += item;
return sum;
}