代码随想录算法训练营第三十三天 1005.K次取反后最大化的数组和、134.加油站、135.分发糖果
1005.K次取反后最大化的数组和
题目链接:力扣题目链接
文章讲解:代码随想录(https://programmercarl.com)
视频讲解:贪心算法,这不就是常识?还能叫贪心?LeetCode:1005.K次取反后最大化的数组和
状态:AC
思路
- 对数组排序,统计负数个数
count
,遍历时再记录绝对值最小的数。
- 如果
count >= k
,那么前k个数全都取反
- 如果
count < k
,说明将负数全都取反后,还有额外的操作次数,判断该次数k - count
是奇数还是偶数,如果是偶数不用操作,如果是奇数,翻转绝对值最小的数
贪心算法
贪尽可能多的正数
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| class Solution { public: int largestSumAfterKNegations(vector<int> &nums, int k) { sort(nums.begin(), nums.end()); int count = 0; int minIndex = 0; for (int i = 0; i < nums.size(); ++i) { if (nums[i] < 0) { count++; } if (abs(nums[i]) < abs(nums[minIndex])) { minIndex = i; } } if (count >= k) { for (int i = 0; i < k; ++i) { nums[i] = -nums[i]; } } else { for (int i = 0; i < count; ++i) { nums[i] = -nums[i]; } if ((k - count) % 2 == 1) { nums[minIndex] = -nums[minIndex]; } } int sum = 0; for (auto i: nums) { sum += i; } return sum; } };
|
134. 加油站
题目链接:力扣题目链接
文章讲解:代码随想录(https://programmercarl.com)
视频讲解:贪心算法,得这么加油才能跑完全程!LeetCode :134.加油站
状态:AC
思路
- 将环路展开成直线的路,即将
gas
数组向后拼接一个自己,cost
向后拼接一个自己,但是去掉一位。
- 外层遍历
gas
,范围从0到gas.size()/2
,索引为i
。内层遍历cost
,范围从i
到i+gas.sise()/2
- 定义当前的油量
cur
,如果cur + gas[j] >= cost[j]
,那么下一次的剩余油量则为cur += gas[j] - cost[j]
。否则从i
开始的路不能走一圈,继续向下遍历
贪心算法
从一点出发贪最远的路
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| class Solution { public: int canCompleteCircuit(vector<int> &gas, vector<int> &cost) { gas.insert(gas.end(), gas.begin(), gas.end()); cost.insert(cost.end(), cost.begin(), cost.end() - 1); for (int i = 0; i < gas.size() / 2; ++i) { int cur = 0; bool flag = true; for (int j = i; j < i + gas.size() / 2; ++j) { if (cur + gas[j] >= cost[j]) { cur += gas[j] - cost[j]; } else { flag = false; i = j; break; } } if (flag) { return i; } } return -1; } };
|
135. 分发糖果
题目链接:力扣题目链接
文章讲解:代码随想录(https://programmercarl.com)
视频讲解:贪心算法,两者兼顾很容易顾此失彼!LeetCode:135.分发糖果
状态:AC
思路
这道题没有想明白,看了题解后懂了。前后两次遍历评分数组。每个人糖果初始化为1。
前向遍历时如果后一项大于前一项,那么后一项的糖果值为前一项加1。
反向遍历时,如果前一项大于后一项时,并且前一项糖果也不超过后一项时,那么前一项糖果等于后一项加1。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class Solution { public: int candy(vector<int> &ratings) { vector<int> result(ratings.size(), 1); for (int i = 1; i < ratings.size(); ++i) { if (ratings[i] > ratings[i - 1]) { result[i] = result[i - 1] + 1; } } for (int i = ratings.size() - 1; i >= 1; --i) { if (ratings[i - 1] > ratings[i] && result[i - 1] <= result[i]) { result[i - 1] = result[i] + 1; } } int sum = 0; for (auto i: result) { sum += i; } return sum; } };
|