1005.K次取反后最大化的数组和
https://leetcode.cn/problems/maximize-sum-of-array-after-k-negations/submissions/505145328/
这道题的关键在于想好怎么才回使得和最大,如果有负数的话,那么应该按照绝对值从大到小的顺序取反,因为绝对值越大的负数取反后越大,所以咱们可以根据绝对值从大到小的顺序排列,如果遇到负数并且k>0就取反,如果k有剩余的话,咱们就考虑k是奇数还是偶数,如果是奇数,就选取绝对值最小的那个取反,这样的话所产生的负数是最小的,如果是偶数的话,就没必要再选了,因为偶数的话不管怎么变还是它本身。
代码要注意:sort里面咱们自定义的bmp应该是static,同时,遍历容器vector要用for(int a:nums)
class Solution {
private:
static bool bmp(int a,int b)
{
return abs(a)>abs(b);
}
public:
int largestSumAfterKNegations(vector<int>& nums, int k) {
sort(nums.begin(),nums.end(),bmp);
for(int i=0;i<nums.size();i++)
{
if(nums[i]<0&&k>0)
{
nums[i]*=-1;
k--;
}
}
if(k%2==1)
{
nums[nums.size()-1]*=-1;
}
int result=0;
for(int a:nums)
{
result+=a;
}
return result;
}
};
134. 加油站
这道题看完Carl哥的视频还是稍许有些绕,我们把问题转化为把每一站剩余的油累积,如果大于等于0说明可以绕一圈,小于0则不可以,绕的点在于start的确定,Carl哥是把一旦累积值<0,那么下一站就是新的起点,这个点很巧妙,正如视频里讲到的疑惑,我也有,我想为啥下一站就是新的起点,前面的不可能有起点了吗,不可能,因为我们假设前面有新的起点,那么新的起点往后是>0,新的起点前面是<=0,但是由于我们是一旦前面的起点<=0了,咱们会自动变更新的起点的,就是不会被前面<=0的拖累,文字讲起来还是有点懵,具体可以看视频。
https://leetcode.cn/problems/gas-station/submissions/505150855/
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;
else
return start;
}
};
135. 分发糖果
我只能说贪心类题目真的好抽象啊啊啊啊啊啊,这道题把它抽象成两边找问题就简单,但这个抽象的过程实在太抽象,这道题用Carl哥的思路是,先按从左到右的顺序,如果后一个比前一个大,后一个就在前面一个的基础上加一,然后再按从右往左的顺序,如果前一个比后一个大,那么前一个就在后一个的基础上加一,注意,这时候加一完的结果可能比原来小(考虑到从左往右遍历的结果),所以咱们应该是取原来的值和加一完的结果的较大的那个数。
https://leetcode.cn/problems/candy/submissions/505362731/
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+1]+1,candyVec[i]);
}
int result=0;
for(int i=0;i<candyVec.size();i++)
{
result+=candyVec[i];
}
return result;
}
};