昨天周日休息,今天又开始刷贪心算法的题目了,开冲!!!
今日任务:
- \1005. K次去取反后最大化的数组和
- 134.加油站
- 135.分发糖果
题目一:1005.K次取反后最大化的数组和
Leetcode题目:【1005.K次取反后最大化的数组和】
参考:【代码随想录之K次取反后最大化的数组和】
自己原有的思路:每次对最小的数进行取反(时间复杂度比较高)
class Solution {
public:
int largestSumAfterKNegations(vector<int>& nums, int k) {
for(int i = 0; i < k; i++){
sort(nums.begin(), nums.end());
nums[0] = -nums[0];
}
int sum = 0;
for(int i = 0; i<nums.size(); i++){
sum += nums[i];
}
return sum;
}
};
卡哥的思路:
(1)对数组中元素的进行绝对值排序,然后遇到负数就取反;
(2)当数组中全部都是正数的时候,但是k还没消耗完,此时就可以只对数组中最小的正数进行取反操作即可。
class Solution {
public:
static bool cmp(int x, int y){
return abs(x) > abs(y);
}
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){
nums[i] = -nums[i];
k--;
}
}
if(k % 2 == 1) nums[nums.size()-1] *= -1;
int sum = 0;
for(int i = 0; i<nums.size(); i++){
sum += nums[i];
}
return sum;
}
};
题目二:134.加油站
Leetcode题目:【134.加油站】
参考:【代码随想录之加油站】
这个题目的思路很巧妙地利用了贪心的思路:
(1)首先把每一站的添加和消耗打包在一起,计算剩余的油量,即图中的cursum;
(2)遍历一轮,如果total_sum < 0,说明根本就不会走完,直接返回-1;
(3)再遍历从哪里开始,如果cursum<0,因为前面已经说明白一定可以走完,所以只需要判断,当前的累计和不能小于0,如果小于0,那就从i+1开始。
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int cur_sum = 0, start = 0, total_sum = 0;
for(int i = 0; i<gas.size(); i++){
total_sum += gas[i] - cost[i];
}
if(total_sum < 0) return -1;
// 在确定能跑完一圈的基础上:
for(int i = 0; i<gas.size(); i++){
cur_sum += gas[i] - cost[i];
if(cur_sum < 0){
start = i+1;
cur_sum = 0;
}
}
return start;
}
};
题目三:135.分发糖果
Leetcode题目:【135.分发糖果】
参考:【代码随想录之分发糖果】
这个题目自己根本想不到,大概的思路为,分为两种情况:左边的孩子比右边孩子分数高、右边的孩子比左边的分数高;
可以模拟老师给学生分发糖果的过程:
(1)老师按顺序给每位学生分发1个糖果;
(2)老师说指令,咱们按顺序来,如果你比你左边的同学分数高,你可以再多拿一个糖果,然后老师从头开始询问;
(3)老师接着在末尾的队伍中中,如果你比你右边的同学分数高,你可以再多拿一棵,然后老师从队尾开始询问;
这个过程也是下面代码的过程(主要按照两种情况去讨论)
class Solution {
public:
int candy(vector<int>& ratings) {
vector<int> candy(ratings.size(), 1);
// 前向遍历:右边孩子比左边孩子大
for(int i = 1; i<ratings.size(); i++){
if(ratings[i] > ratings[i-1]){
candy[i] = candy[i-1] + 1;
}
}
// 后向遍历:左边孩子比右边孩子大
for(int i = ratings.size() -2; i>=0; i--){
if(ratings[i] > ratings[i+1]){
candy[i] = max(candy[i], candy[i+1] + 1);
}
}
int sum = 0;
for(int i = 0; i<candy.size(); i++){
sum += candy[i];
}
return sum;
}
};