1005.K次取反后最大化的数组和
题目链接:1005.K次取反后最大化的数组和
贪心策略:按照绝对值从大到小排序是为了将最大负数优先转为正数,且如果k还有剩余,让反转到最后一个绝对值最小的数字上。
class Solution {
public:
int largestSumAfterKNegations(vector<int>& nums, int k) {
sort(nums.begin(), nums.end(),
[](const auto& lhs, const auto& rhs) {
return abs(lhs) > abs(rhs);
});//按照绝对值从大到小排序
for (auto& num : nums) {
if (num < 0 && k > 0) {
num *= -1;
--k;
}
}
if (k % 2 == 1) nums.back() *= -1;//当经过上一步遍历如果k还有剩下,则运行这一步代码
int res = 0;
for (auto& num : nums) res += num;
return res;
}
};
134. 加油站
题目链接:134. 加油站
设置一个当前和curSum
是记录从第0
个加油站到第i
个加油站中消耗和补充的总和。如果总和为负数,则满足题意的加油站不可能是从i
(包括i
)之前开始的,因为加油站是从索引为0
开始遍历的。
设置一个所有总和totalSum
是记录所有的补充消耗和,如果totalSum < 0
,则无论从哪个开始都不能绕一圈。
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int curSum = 0, totalSum = 0;
int res = 0;//初始化为零,并不只是常规初始化。这个零还有一层作用,如果curSum始终大于零,则该函数输入res = 0的0
for (int i = 0; i < gas.size(); ++i) {
curSum += (gas[i] - cost[i]);
totalSum += (gas[i] - cost[i]);
if (curSum < 0) {//需要重新统计
curSum = 0;
res = i + 1;
}
}
if (totalSum < 0) return -1;
return res;
}
};
135. 分发糖果
题目链接:135. 分发糖果
遇到两个维度,不要同时考虑(不要想一个循环就解决)。
先从左往右比较,再从右侧往左比较
class Solution {
public:
int candy(vector<int>& ratings) {
vector<int> child(ratings.size(), 1);
//向右遍历,右侧大于左侧,右侧为左侧+1
for (int i = 1/*从1开始,0没有左侧*/; i < ratings.size(); ++i) {
if (ratings[i] > ratings[i - 1]) {
child[i] = child[i - 1] + 1;
}
}
//向左遍历,左侧大于右侧,左侧为右侧+1,同时要和向右遍历的取最大值,因为满足上一个遍历的同时满足本次
for (int i = ratings.size() - 2/*从-2开始。-1没有右侧*/; i >= 0; --i) {
if (ratings[i] > ratings[i + 1]) {
child[i] = max(child[i + 1] + 1, child[i]);
}
}
int res = 0;
for (auto& i : child) res += i;
return res;
}
};