1005.K次取反后最大化的数组和
题目链接
(1)文字讲解:https://programmercarl.com/1005.K%E6%AC%A1%E5%8F%96%E5%8F%8D%E5%90%8E%E6%9C%80%E5%A4%A7%E5%8C%96%E7%9A%84%E6%95%B0%E7%BB%84%E5%92%8C.html
(2)视频讲解:https://www.bilibili.com/video/BV138411G7LY/?spm_id_from=333.788&vd_source=bca249a7a739de13f222d238e1152887
(3)题目链接:
https://leetcode.cn/problems/maximize-sum-of-array-after-k-negations/submissions/
看到代码随想录之前的想法
我会把负数和正数拆开成为两个向量。负向量从大的开始变成正的。如果还剩下k可以用,从小的开始吧正向量变成负的然后再求和。
看到代码随想录之后的想法
没有想到当k没有消耗完的时候应该找最小的那个元素反复消耗,这一点忽略了。以及不需要吧正负两个分开,只需要写一个利用绝对值排序的cmp函数就可以不改变正负号的情况下排序。
本题难点
第二次没有消耗完的k的贪心。
代码
class Solution {
static bool cmp(int a, int b){
return abs(a) > abs(b);
}
public:
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] *= -1;
k--;
}
}
if(k % 2 == 1) nums[nums.size()-1] *= -1;
int result = 0;
for(int i = 0; i < nums.size(); i++)
{
result += nums[i];
}
return result;
}
};
134. 加油站
题目链接
(1)文字讲解:https://programmercarl.com/0134.%E5%8A%A0%E6%B2%B9%E7%AB%99.html#%E6%9A%B4%E5%8A%9B%E6%96%B9%E6%B3%95
(2)视频讲解:https://www.bilibili.com/video/BV1jA411r7WX/?spm_id_from=333.788&vd_source=bca249a7a739de13f222d238e1152887
(3)题目链接:
https://leetcode.cn/problems/gas-station/
看到代码随想录之前的想法
纯暴力,每一个加油站都开始一次直到满足条件。
for循环适合模拟从头到尾的遍历,而while循环适合模拟环形遍历,要善于使用while!
代码:
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
for (int i = 0; i < cost.size(); i++) {
int rest = gas[i] - cost[i]; // 记录剩余油量
int index = (i + 1) % cost.size();
while (rest > 0 && index != i) { // 模拟以i为起点行驶一圈(如果有rest==0,那么答案就不唯一了)
rest += gas[index] - cost[index];
index = (index + 1) % cost.size();
}
// 如果以i为起点跑一圈,剩余油量>=0,返回该起始位置
if (rest >= 0 && index == i) return i;
}
return -1;
}
};
看到代码随想录之后的想法
1.算出每个加油站的差值,这个就是能剩多少。
2.开始遍历每个节点的差值,设置一个cursum记录目前油箱里面还有多少油。如果小于0,说明从这个点开始是绝对不行的,cursum归零,从i+1开始试起。如果一直到终点cursum仍然大于0,说明目前的i就是答案。
3.因为这道题记录了totalsum,如果totalsum大于0,说明从哪开始都不行。只要排除了这个可能,说明totalsum是大于0的。这样的话从i开始到末尾已经是大于0了,不管前面0-i的区间和负值有多大,都没关系,因为总的区间和totalsum是>0,所以cursum > |sum[0,i-1]|,能保证一直不是负数。
本题难点
1.想到这种想法很难。
2.证明这种想法是合理的(也就是文章中的证明和我上面的第3小点)
代码
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int cursum = 0,totalsum = 0, result = 0;
for(int i = 0; i < gas.size(); i++){
cursum += gas[i] - cost[i];
totalsum += gas[i] - cost[i];
if(cursum < 0){
result = i+1;
cursum = 0;
}
}
if(totalsum < 0) return -1;
return result;
}
};
135. 分发糖果
题目链接
(1)文字讲解:https://programmercarl.com/0135.%E5%88%86%E5%8F%91%E7%B3%96%E6%9E%9C.html#%E6%80%9D%E8%B7%AF
(2)视频讲解:https://www.bilibili.com/video/BV1ev4y1r7wN/?spm_id_from=333.788&vd_source=bca249a7a739de13f222d238e1152887
(3)题目链接:https://leetcode.cn/problems/candy/
看到代码随想录之前的想法
先从左边开始向右,仅仅考虑右边的比左边的大的情况。然后从右到左,考虑左边比右边大,目前的是否符合糖果分配的条件,如果不符合再去加。
看到代码随想录之后的想法
同上。
本题难点
一定要分开去考虑左边和右边。
代码
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 result = 0;
for(int i = 0 ; i < candy.size(); i++){
result += candy[i];
}
return result;
}
};
599

被折叠的 条评论
为什么被折叠?



