目录
一、1005. K 次取反后最大化的数组和
二、134. 加油站
三、135. 分发糖果
一、1005. K 次取反后最大化的数组和
题目链接:力扣
文章讲解:代码随想录
视频讲解:
题目:
给你一个整数数组 nums 和一个整数 k ,按以下方法修改该数组:
选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。
重复这个过程恰好 k 次。可以多次选择同一个下标 i 。
以这种方式修改数组后,返回数组 可能的最大和 。
代码:
class Solution {
public:int largestSumAfterKNegations(vector<int>& nums, int k) {sort(nums.begin(), nums.end());int position = 0;int sum = 0;for(int i = 0; i < nums.size(); i++){if(nums[i] < 0 && k > 0){k--;nums[i] = -nums[i];position = i;}sum += nums[i];}if (k > 0){if(k%2 == 1) return sum - 2*(nums[position] > nums[(position+1)%nums.size()] ? nums[(position+1)%nums.size()] : nums[position]);else return sum; }return sum;}
};
时间复杂度: O(n+c) 空间复杂度:O(c)
⏲:9:19
总结:取负:局部最优:最大的负数先取负。转变k次正负:局部最优:最小的数。
二、134. 加油站
题目链接:134. 加油站 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)
视频讲解:
题目:在一条环路上有 n 个加油站,其中第 i 个加油站有汽油 gas[i] 升。 你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。 给定两个整数数组 gas 和 cost ,如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1 。如果存在解,则 保证 它是 唯一 的。代码:
class Solution {
public:int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {int sum = 0;int total = 0;int position = 0;int flag = 0;for (int i = 0; i < gas.size(); i++){sum += gas[i] - cost[i];total += gas[i] - cost[i];if(sum < 0){sum = 0;position = i+1;}} if(total<0) return -1;return position;}
};
时间复杂度: O(n) 空间复杂度O(1)
⏲:25:07
总结:局部最优:当sum<0则合理位置至少i+1,i+1之前都不行。本质:如果总数为正,则应该正大于负,局部来看,若前面的和为负数,则后面的和应为正数。
三、135. 分发糖果
题目链接:135. 分发糖果 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)
视频讲解:
题目:n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。 你需要按照以下要求,给这些孩子分发糖果: 每个孩子至少分配到 1 个糖果。 相邻两个孩子评分更高的孩子会获得更多的糖果。 请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。代码:
class Solution {
public:int candy(vector<int>& ratings) {vector<int> candyvec(ratings.size(), 1);for (int i = 1; i < ratings.size(); i++)//从左到右if (ratings[i] > ratings[i-1]) candyvec[i]= candyvec[i-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 ans = 0;for (int &i : candyvec)ans += i;return ans;}
};class Solution {
public:int candy(vector<int>& ratings) {vector<int> left(ratings.size(), 1);vector<int> right(ratings.size(), 1);for(int i = 1, j = ratings.size()-2; i < ratings.size(); j--, i++){if(ratings[i] > ratings[i-1]) left[i] = left[i-1]+1;if(ratings[j] > ratings[j+1]) right[j] = right[j+1]+1;} int sum = 0;for(int i = 0; i < ratings.size(); i++){sum += max(left[i], right[i]);}return sum;}
};
时间复杂度: O(n) 空间复杂度O(1)
⏲:4:38
总结:重点:两边同时比较会顾此失彼。注意点:右与左比较时只能正向遍历,反向遍历会错失评分连续增长的情况(总之就是两个方向各来一遍)。
ps:多个维度考虑时,一般先考虑一个维度,再考虑另外一个维度。