1005.K次取反后最大化的数组和(简单)
leetcode题目链接:1005. K 次取反后最大化的数组和 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)
视频讲解:贪心算法,这不就是常识?还能叫贪心?LeetCode:1005.K次取反后最大化的数组和_哔哩哔哩_bilibili
解题思路
我们将数组按绝对值大小进行排序,每次对负数取反就行。如果遍历完数组,k还没消耗完,就对最小的整数取反。如果k是奇数就取一次,是偶数就不用取反。
如果不按绝对值大小进行排序,会导致多次排序,下面我会贴出两种代码对比。
题目代码
不按绝对值
class Solution {
public:
int largestSumAfterKNegations(vector<int>& nums, int k) {
sort(nums.begin(), nums.end());
int sum = 0;
for (int i = 0; i < nums.size(); i++)
{
if (nums[i] >= 0 && k != 0)
{
sort(nums.begin(), nums.end());
for (k; k > 0; k--)
nums[0] = -nums[0];
break;
}
nums[i] = -nums[i];
k--;
if (k == 0)
break;
}
sort(nums.begin(), nums.end());
if(k%2==1) nums[0]=-nums[0];
for (auto& r : nums)
sum += r;
return sum;
}
};
按绝对值
class Solution {
static bool cmp(int a, int b) {
return abs(a) > abs(b);
}
public:
int largestSumAfterKNegations(vector<int>& A, int K) {
sort(A.begin(), A.end(), cmp); // 第一步
for (int i = 0; i < A.size(); i++) { // 第二步
if (A[i] < 0 && K > 0) {
A[i] *= -1;
K--;
}
}
if (K % 2 == 1) A[A.size() - 1] *= -1; // 第三步
int result = 0;
for (int a : A) result += a; // 第四步
return result;
}
};
134. 加油站(中等)
leetcode题目链接:134. 加油站 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)
视频讲解:贪心算法,得这么加油才能跑完全程!LeetCode :134.加油站_哔哩哔哩_bilibili
题目描述
解题思路
其实本题有点像最大子数组和那个题。
如果从0或1开始,剩余加到2时,必然是负数,也就是说从0,1开始均不可能回到起点。
那么我们如果遍历中遇到和是负数的情况,就从第i+1(2+1=3)这个位置再开始尝试。
遍历完数组后,如果总的剩余和也是负数,那就代表不论从哪走,都不可能回到起点。
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int curSum = 0;
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;
return start;
}
};
135. 分发糖果 (困难)
leetcode题目链接:135. 分发糖果 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)
视频讲解:贪心算法,两者兼顾很容易顾此失彼!LeetCode:135.分发糖果_哔哩哔哩_bilibili
题目描述
解题思路
如果我们同时比较左右两边,很容易比错。我们可以这么做。
第一遍遍历,只看右边孩子大于左边的情况,如果大于,右边孩子糖果数就是左边+1。
第二遍遍历,倒着遍历,只看左边孩子大于右边的情况,如果大于,就取当前糖果数和右边糖果数+1的最大值。
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 (auto r : Candy)
sum += r;
return sum;
}
};