算法夏令营Day34 第八章 贪心算法 part3

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

        这道题可以先对数组进行排序,排序规则为绝对值大的在前面,绝对值小的在后面。之后,遍历数组,如果k > 0并且当前遍历到的值小于0,那就k--,并且让这个负数取绝对值。遍历完整个数组之后,如果k对2取余数为1,此时数组中的树全部为非负数,说明还需要对最小的那个数*(-1),最小的那个数就是数组的最后一个元素。

代码如下:

class Solution {
public:
    static bool mycmp(int num1, int num2) {
        return abs(num1) > abs(num2);
    }

    int largestSumAfterKNegations(vector<int>& nums, int k) {
        sort(nums.begin(), nums.end(), mycmp);
        for(int i = 0; i < nums.size(); ++i) {
            if(k > 0 && nums[i] < 0) {
                nums[i] *= -1;
                k--;
            }
        }
        if(k % 2 == 1) nums[nums.size() - 1] *= -1;
        int sum = 0;
        for(int j = 0; j < nums.size(); ++j) {
            sum += nums[j];
        }
        return sum;
    }
};

第二题: 134. 加油站

        这道题比较容易想到暴力解法,但会写成两个嵌套的for循环,时间复杂度为O(n^{2})。其实这道题可以使用贪心算法巧妙地解决问题,但是思路不太好想到。可以设置一个变量curSum来记录从当前位置开始,行驶过程中添加总油量与消耗总油量之差;变量totalSum来记录总行驶路程中添加油量与消耗油量之差;start来记录可以实现题意的起始位置。从头开始遍历,如果curSum小于0,则说明从这个位置及以前开始行驶都不能完成题目要求。如果totalSum小于0,则说明没有一个位置开始能完成。

代码如下:

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

第三题: 135. 分发糖果

        这道题一定是要先确定一边之后,再确定另一边,例如:先比较每一个孩子的左边,然后再比较右边,如果两边一起考虑一定会顾此失彼。所以,我们可以考虑使用两次for循环,第一次用于从前向后遍历,第二次则是从后向前遍历。第一次遍历时,考虑只要当前孩子比前一个孩子成绩高,就先给他比前一个孩子多分一个糖果,否则先给他分一个糖果;第二次遍历时,当前孩子比后一个孩子的成绩高,且所分糖果不大于后一个孩子的糖果数目,就令他的糖果比后一个孩子的糖果多一个。

代码如下:

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], candyVec[i + 1] + 1);
            }
        }
        // 统计结果
        int result = 0;
        for (int i = 0; i < candyVec.size(); i++) result += candyVec[i];
        return result;
    }
};

        Day34打卡!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值