1005.K次取反后最大化的数组和
题目链接:
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
求解思路:
两次贪心
- 如果数组中有负数,那么从小到大将所有的负数都转为正数
- 如果数组中没有负数,那么只找最小的正数重复反转
下面的代码怒而击败5%的人,优化空间很大
代码:
class Solution {
public:
int largestSumAfterKNegations(vector<int>& nums, int k) {
while(k--){
// 每次都排序一次,转换最小的值
sort(nums.begin(), nums.end());
nums[0] = -1 * nums[0];
}
int sum = 0;
for (int i = 0; i < nums.size(); i++){
sum += nums[i];
}
return sum;
}
};
134. 加油站
题目链接:
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
求解思路:
- 每个加油站的剩余量rest[i]为gas[i] - cost[i],如果rest[i]的总和小于0,那么不可能跑完一圈
- i从0开始累加rest[i],和记为curSum,一旦curSum小于零,说明[0, i]区间都不能作为起始位置,因为这个区间选择任何一个位置作为起点,到i这里都会断油,那么起始位置从i+1算起,再从0计算curSum
代码:
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int curSum = 0; // 当前消耗(gas-cost)
int totalSum = 0; // 总消耗
int start = 0;
for (int i = 0; i < gas.size(); i++){
curSum += (gas[i] - cost[i]);
totalSum += (gas[i] - cost[i]);
// 如果当前消耗为负数,则将后一个位置作为起点
if (curSum < 0){
start = i + 1;
curSum = 0;
}
}
if (totalSum < 0) return -1; // 如果总消耗小于0,则不可能走完全程
return start;
}
};
135. 分发糖果
题目链接:
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
求解思路:
- 先确定右边评分大于左边的情况(从前向后遍历),只要右边评分比左边大,右边的孩子就多一个糖果
- 再确定左孩子大于右孩子的情况(从后向前遍历),此时要保证保证第i个小孩的糖果数量既大于左边的也大于右边的,所以取原先数组和右孩子糖果+1之间更大的值
代码:
class Solution {
public:
int candy(vector<int>& ratings) {
vector<int> candyVec(ratings.size(), 1); // 全部初始化为1
// 从左往右遍历,如果右边的孩子比左边的孩子分高,则右边的孩子糖果+1
for (int i = 1; i < ratings.size(); i++){
if (ratings[i] > ratings[i-1])
candyVec[i] = candyVec[i-1]+1;
}
// 从右往左遍历,如果左边的孩子比右边的孩子分高
// 则取 左边的孩子糖果+1 和 原先数组中元素 较大的那个
for (int i = ratings.size()-2; i >= 0; i--){
if (ratings[i] > ratings[i+1])
candyVec[i] = max(candyVec[i], candyVec[i+1]+1);
}
int result = 0;
for (int n : candyVec){
result += n;
}
return result;
}
};