算法训练营day34_贪心算法(3.6)

算法训练营day33_贪心算法(3.6)

1005.k次取反后最大化的数组和

先排个序;

如果k<=负数个数,从小到大修改负数->正数,修改k次;

如果k>负数个数,那么多出的次数如果是偶数,就不用管(这时候都是正值,一直逮着一个薅,还是原来的值);如果多出的次数是奇数,那就得找个最小的正数->负数(我刚开始掉坑里了,我直接找原数组里最小的正数,第一可能原数组中没有正数,第二若原数组里有负数,可能最小正数是负数最大值转化而来的);

**随想录思路:**改一下排序规则,绝对值从大到小排序,遇到负值就改正数,有多出的k就薅最小的数,这个思路很好,可以直接得出负数改为正数后处于什么位置,我那个没有办法得出,我是通过初始在数组的位置判断的,get了;

class Solution {
public:
    int largestSumAfterKNegations(vector<int>& nums, int k) {
        int n=nums.size();
        int cnt=0,ans=0;
        for(int i=0;i<n;i++){
            if(nums[i]<0) cnt++;
        }
        sort(nums.begin(),nums.end());
        if(k<=cnt){
            for(int i=0,t=0;i<n;i++){
                if(t<k){
                    nums[i]=-nums[i];
                    t++;
                }
                ans+=nums[i];
            }
        }
        else{
            for(int i=0;i<n;i++){
                ans+=abs(nums[i]);
            }
            if((k-cnt)&1){
                int minm=1e9;
                if(cnt<n) minm=min(minm,nums[cnt]);
                if(cnt>0) minm=min(minm,abs(nums[cnt-1]));
                cout<<minm<<endl;
                ans-=minm*2;
            }
        }
        return ans;
    }
};

134.加油站

由gas,cost数组做差可得一个数组,表示到下一个站油量变化;

如果差数组加和<0,说明油量会在某一点变为负值,显然不合理;

遍历一遍,更新cur(到当前点的油量),如果某一点cur<0,说明它之前的加油站都不能作为起点(这一点我也想到了当时,我当时没想到只需要这一个条件即可),cur刷新为0,加油站更新为i+1;假设最后答案为ans,ans之前的加油站肯定是不能作为起点,ans之后也没有出现cur<0的情况,所以很合理;

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int n=gas.size();
        int sum=0,cur=0,ans=0;
        for(int i=0;i<n;i++){
            sum+=gas[i]-cost[i];
            cur+=gas[i]-cost[i];
            if(cur<0){
                cur=0;
                ans=i+1;
            }
        }
        if(sum<0) return -1;
        return ans;
    }
};

135.分发糖果

这道题之前做过类似的;

每个人至少一个,故创建数组要初始化为1个,相邻包括左相邻,右相邻;

先考虑左相邻,从左往右遍历,如果比左边数大,值就为左边数+1;

再考虑右相邻,从右往左遍历,如果比右边数大,值就为右边数+1;

由于左右都要满足,最后取左右两个数组的最大值;

class Solution {
public:
    int candy(vector<int>& ratings) {
        int n=ratings.size();
        vector<int> l(n,1),r(n,1);
        for(int i=1;i<n;i++){
            if(ratings[i]>ratings[i-1]) l[i]=l[i-1]+1;
        }
        for(int i=n-2;i>=0;i--){
            if(ratings[i]>ratings[i+1]) r[i]=r[i+1]+1;
        }
        int sum=0;
        for(int i=0;i<n;i++) sum+=max(l[i],r[i]);
        return sum;
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值