1005.K次取反后最大化的数组和
思路:本题有两次贪心,第一次是找绝对值最大的负数,优先对其进行取反,对我们求最大数组和是有帮助的(局部最优推全局最优),第二次贪心就是如果遍历完数组之后k还没有用完(此时所有的负数都变成了正数),那我们就取这个数组里最小的数,把k消耗完(局部最优)。
class Solution {
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){//因为k一直做减减,所以也要判断k
nums[i]*=-1;
k--;
}
}
//如果遍历完之后k还没有用完(那一定负数就都变成正数了)
if(k%2==1) nums[nums.size()-1]*=-1;
int result=0;
for(int i=0;i<nums.size();i++){
result+=nums[i];
}
return result;
}
};
在类的成员函数前面加static关键字,说明成员函数是属于类的,而非对象的,也就是所有该类的对象共同拥有这一个成员函数,而不是普通的每个对象各自拥有一个成员函数。
总之,static关键字可以用于将函数的变量和作用域限制在当前类、函数或文件中,使得代码更加模块化和封装化。
参考:https://blog.csdn.net/lulu_6666/article/details/79570335
https://blog.csdn.net/cw616729/article/details/95003577
134. 加油站
思路:本题的局部最优就是不断累加cursum,一旦小于0了,就选择下一个站点作为起点,全局最优是我们找到能够跑完一圈的起点位置。
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int cursum=0;
int totalsum=0;
int start=0;//先从0开始,之后如果加着加着cursum小于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;
return start;
}
};
135. 分发糖果
思路:题目中说了,相邻两个孩子评分更高的孩子会获得更多的糖果,那如果相同的话,就还是默认1个,本题每个孩子的糖果,既要和左边孩子进行比较,也要和右边孩子进行比较,那如果同时进行比较的话,一定会顾此失彼的,所以我们先确定一边,再确定另一边。首先只看右边比左边得分高的情况,再只看左边比右边得分高的情况。
class Solution {
public:
int candy(vector<int>& ratings) {
vector<int> candy(ratings.size(),1);
for(int i=1;i<ratings.size();i++){
if(ratings[i]>ratings[i-1]){
candy[i]=candy[i-1]+1;
}
}
for(int i=ratings.size()-2;i>=0;i--){
if(ratings[i]>ratings[i+1]){
candy[i]=max(candy[i],candy[i+1]+1);//要比较一下,既要比左边小孩的糖果数量多,也要比右边小孩的糖果数量多
}
}
int result=0;
for(int i=0;i<candy.size();i++){
result+=candy[i];
}
return result;
}
};
错因:忘了和第一种情况比较取max了。