【Day34】代码随想录之贪心算法part03——K次取反后最大化的数组和、加油站、分发糖果

昨天周日休息,今天又开始刷贪心算法的题目了,开冲!!!

今日任务:

  • \1005. K次去取反后最大化的数组和
  • 134.加油站
  • 135.分发糖果

题目一:1005.K次取反后最大化的数组和

Leetcode题目:【1005.K次取反后最大化的数组和】
参考:【代码随想录之K次取反后最大化的数组和】

在这里插入图片描述

自己原有的思路:每次对最小的数进行取反(时间复杂度比较高)


class Solution {
public:
    int largestSumAfterKNegations(vector<int>& nums, int k) {
        for(int  i = 0; i < k; i++){
            sort(nums.begin(), nums.end());
            nums[0] = -nums[0];
        }
        int sum = 0;
        for(int i = 0; i<nums.size(); i++){
            sum += nums[i];
        }
        return sum;
    }
};

卡哥的思路:
(1)对数组中元素的进行绝对值排序,然后遇到负数就取反;
(2)当数组中全部都是正数的时候,但是k还没消耗完,此时就可以只对数组中最小的正数进行取反操作即可。

class Solution {
public:
    static bool cmp(int x, int y){
        return abs(x) > abs(y);
    }
    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] = -nums[i];
                k--;
            }
        }
        if(k % 2 == 1) nums[nums.size()-1] *= -1;

        int sum = 0;
        for(int i = 0; i<nums.size(); i++){
            sum += nums[i];
        }
        return sum;
    }
};

题目二:134.加油站

Leetcode题目:【134.加油站】
参考:【代码随想录之加油站】

在这里插入图片描述

在这里插入图片描述

这个题目的思路很巧妙地利用了贪心的思路:
(1)首先把每一站的添加和消耗打包在一起,计算剩余的油量,即图中的cursum;
(2)遍历一轮,如果total_sum < 0,说明根本就不会走完,直接返回-1;
(3)再遍历从哪里开始,如果cursum<0,因为前面已经说明白一定可以走完,所以只需要判断,当前的累计和不能小于0,如果小于0,那就从i+1开始。

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int cur_sum = 0, start = 0, total_sum = 0;
        for(int i = 0; i<gas.size(); i++){
            total_sum += gas[i] - cost[i];
        }
        if(total_sum < 0) return -1;
        
        // 在确定能跑完一圈的基础上:
        for(int i = 0; i<gas.size(); i++){
            cur_sum += gas[i] - cost[i];
            if(cur_sum < 0){
                start = i+1;
                cur_sum = 0;
            }
        }
        return start;

    }
};

题目三:135.分发糖果

Leetcode题目:【135.分发糖果】
参考:【代码随想录之分发糖果】

在这里插入图片描述

这个题目自己根本想不到,大概的思路为,分为两种情况:左边的孩子比右边孩子分数高、右边的孩子比左边的分数高;
可以模拟老师给学生分发糖果的过程:
(1)老师按顺序给每位学生分发1个糖果;
(2)老师说指令,咱们按顺序来,如果你比你左边的同学分数高,你可以再多拿一个糖果,然后老师从头开始询问;
(3)老师接着在末尾的队伍中中,如果你比你右边的同学分数高,你可以再多拿一棵,然后老师从队尾开始询问;

这个过程也是下面代码的过程(主要按照两种情况去讨论)

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 sum = 0;
        for(int i = 0; i<candy.size(); i++){
            sum += candy[i];
        }
        return sum;

    }
};
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值