代码随想录第三十四天|Leetcode1005.K次取反后最大化的数组和、Leetcode134. 加油站、Leetcode135. 分发糖果
Leetcode1005.K次取反后最大化的数组和
题目链接:Leetcode1005.K次取反后最大化的数组和
熟悉熟悉这个sort函数自定义排序方法的用法
class Solution {
private:
static bool cmp(int a,int b){
return abs(a)>abs(b);
}
public:
int largestSumAfterKNegations(vector<int>& nums, int k) {
sort(nums.begin(),nums.end(),cmp);
for(int i=0;i<nums.size();i++){
if(nums[i]<0 && k>0){
nums[i]*=-1;
k--;
}
}
int sum=0;
if(k%2==1) nums[nums.size()-1]*=-1;
for(int num:nums) sum+=num;
return sum;
}
};
Leetcode134. 加油站
题目链接:Leetcode134. 加油站
本来不想动脑了,先整个双for循环暴力解试试,又遇到了力扣的暴力杀手用例,被拿下了。
答案给了个很巧妙的方法:
- 如果gas的总和小于cost总和,那么无论从哪里出发,一定是跑不了一圈的
- rest[i] = gas[i]-cost[i]为一天剩下的油,i从0开始计算累加到最后一站,如果累加没有出现负数,说明从0出发,油就没有断过,那么0就是起点。
- 如果累加的最小值是负数,汽车就要从非0节点出发,从后向前,看哪个节点能把这个负数填平,能把这个负数填平的节点就是出发节点。
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int curSum = 0;
int min = INT_MAX; // 从起点出发,油箱里的油量最小值
for (int i = 0; i < gas.size(); i++) {
int rest = gas[i] - cost[i];
curSum += rest;
if (curSum < min) {
min = curSum;
}
}
if (curSum < 0) return -1; // 情况1
if (min >= 0) return 0; // 情况2
// 情况3↓
for (int i = gas.size() - 1; i >= 0; i--) {
int rest = gas[i] - cost[i];
min += rest;
if (min >= 0) {
return i;
}
}
return -1;
}
};
还有个非常nb的方法,这个思路真的牛逼: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;
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) {
// 当前累加rest[i]和 curSum一旦小于0
start = i + 1; // 起始位置更新为i+1
curSum = 0; // curSum从0开始
}
}
if (totalSum < 0) return -1; // 说明怎么走都不可能跑一圈了
return start;
}
};
Leetcode135. 分发糖果
离独立做出困难题最近的一次,一定要二刷
二刷提醒
最核心的易错点有三个:
- 不要想着同时考虑两边,左大于右,右大于左,分开考虑。
- 对下一个进行判断时要记得用上上一个值,比如123,判断23时要用上12的判断结果
- 倒着判断时,要记得是max,因为之前已经赋值过一次了,要判断当前值和前值加一哪个更大
class Solution {
public:
int candy(vector<int>& ratings) {
vector<int> nums(ratings.size(),1);
//右>左
for(int i=1;i<ratings.size();i++){
if(ratings[i]>ratings[i-1]) nums[i]=nums[i-1]+1;
}
//左>右
for(int i=ratings.size()-2;i>=0;i--){
if(ratings[i]>ratings[i+1]) nums[i]=max(nums[i],nums[i+1]+1);
}
int result=0;
for(int i=0;i<nums.size();i++){
result+=nums[i];
}
return result;
}
};