代码随想录算法训练营Day 33 | LeetCode1005.K次取反后最大化的数组和、LeetCode134. 加油站、LeetCode135. 分发糖果

LeetCode1005.K次取反后最大化的数组和

本题较为简单,一开始的思路是先从小到大排序,然后当处理完负数时,再重新从小到大排序,处理正数,或者维护一个绝对值最小的数的下标。

那么其实可以直接对nums进行绝对值排序,这样就不需要排序两遍了,需要自己额外定义一个cmp函数。

代码如下,时间复杂度即为排序算法时间复杂度;空间复杂度O(1).

class Solution {
public:
    static bool cmp(int a,int b){
        return abs(a)>abs(b);
    }   
    int largestSumAfterKNegations(vector<int>& nums, int k) {
        sort(nums.begin(),nums.end(),cmp);
        int result = 0;
        for(int i=0;i<nums.size();i++){
            if(k>0 && nums[i]<0){
                nums[i] = -nums[i];
                k--;
            }
            result +=nums[i];
        }
        if(k%2==1){
            result -= 2*nums[nums.size()-1];
        }        
        return result;
    }
};

LeetCode134. 加油站

本题通过将汽油和路程巧妙做差,相当于对一个数组进行处理。假使本题一定可以走完一圈,那么start位置一定会在我们遍历一遍数组之后被记录到,因为位置肯定是从curSum之后的一个位置开始的,如果最后没有记录到start值,需要判断totalSum,并且在返回start之前返回,表示不存在start值。

代码如下:时间复杂度O(n),空间复杂度O(1)。

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;
        return start;
    }
};

LeetCode135. 分发糖果

这道题两边一起比较一定会顾此失彼,举个例子,一个数需要与旁边两个数比较,当左边数大,右边数小时,不只需要对当前数做处理,还需要对前一个已经处理过的数再重新做处理,如果对于前一个数来说也是相同的情况,就会比较复杂了,因此应该一边一边的处理,由于当我们遍历的时候,需要与左边的数进行比较,这个特性就决定我们需要从后往前遍历,这样才能正确的更新左边数对应的糖果,同样的,利用从前往后遍历更新右边数对应的糖果,这样就能够得到正确的nums数组,最后输出和。

代码如下:时间复杂度O(n);空间复杂度O(n)。

class Solution {
public:
    int candy(vector<int>& ratings) {
        vector<int> nums(ratings.size(),1);
        int result = 0;
        for(int i=0;i<ratings.size()-1;i++){
            if(ratings[i]<ratings[i+1] && nums[i]>=nums[i+1]){
                nums[i+1] = nums[i]+1;
            }
        }
        for(int i=ratings.size()-1;i>0;i--){
            if(ratings[i-1]>ratings[i] && nums[i-1]<=nums[i]){
                nums[i-1] = nums[i]+1;
            }
        }
        for(int i=0;i<nums.size();i++){
            result += nums[i];
        }
        return result;
    }
};

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值