代码随想录算法训练营第三十四天 | 1005. K 次取反后最大化的数组和、134. 加油站、135. 分发糖果
1005. K 次取反后最大化的数组和
题目链接:1005. K 次取反后最大化的数组和
- 局部最优:最小的负数变为正数, 正数或者0用偶数次k不变或者奇数次变最小的
- 整个数组和达到最大。
- 要考虑绝对值最小的负数变为正数之后K还剩,那么需要把K用完的应该是那个元素
-
class Solution { public: int largestSumAfterKNegations(vector<int>& nums, int k) { int total = 0; sort(nums.begin(), nums.end()); for (int i = 0; i < nums.size(); ++i) { if(nums[i] < 0) { if(k > 0) { nums[i] = - nums[i]; k--; } else { continue; } } } if(k > 0) { // 说明负数都变为正数后还有次数没用完 sort(nums.begin(), nums.end()); while(k != 0) { k--; nums[0] = -nums[0]; } } for (int i = 0; i < nums.size(); i++) { total += nums[i]; } return total; } };
134. 加油站
题目链接:134. 加油站
- 局部最优:剩油量一定是大于等于0的
- 整体最优:走完全程
- 暴力法
- 贪心法:从i出发如果无法到j,那么这中间的任意点出发也无法到达
- 画图法:最低点出发最可能到达终点
135. 分发糖果
题目链接:135. 分发糖果
- 局部最优:左边的比右边的高一,右边的比左边的高一
- 左边扫一遍,右边扫一遍
-
class Solution { public: int candy(vector<int>& ratings) { int len = ratings.size(); vector<int> left(len); for (int i = 0; i < len; ++i) { if (i > 0 && ratings[i] > ratings[i - 1]) { left[i] = left[i - 1] + 1; } else { left[i] = 1; } } int ans = 0; for(int i = len - 1; i >= 0; --i) { if(i < len - 1 && ratings[i] > ratings[i + 1]) { left[i] = max(left[i], left[i + 1] + 1); } ans += left[i]; } return ans; } };