代码随想录Day34 | 1005.K次取反后最大化的数组和 134. 加油站 135. 分发糖果

代码随想录Day34 | 1005.K次取反后最大化的数组和 134. 加油站 135. 分发糖果

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

文档讲解:代码随想录
视频讲解: 贪心算法,这不就是常识?还能叫贪心?LeetCode:1005.K次取反后最大化的数组和
状态

尽可能翻转所有负数,如果k比负数个数多,那么就不断翻转最小的数(包括负数的绝对值)。

//选择最小的数进行翻转
class Solution {
public:
    int largestSumAfterKNegations(vector<int>& nums, int k) {
        sort(nums.begin(),nums.end());
        //统计负数
        int nenums = 0;
        for(int i = 0;i<nums.size();i++)
        {
            if(nums[i]<0)
            {
                nenums++;
            }
        }
        //返回的结果
        int res = 0;
        //当nenums为0
        if(nenums == 0)
        {
            if(k%2==0)
            {
                for(int i = 0;i<nums.size();i++)
                {
                    res += nums[i];
                }
            }
            else
            {
                res += -1*nums[0];
                for(int i = 1;i<nums.size();i++)
                {
                    res += nums[i];
                }
            }
        }
        //当nenums 不为0且小于k
        else
        {
            if(nenums<k)
            {
                for(int i = 0;i<nums.size();i++)
                {
                    if(i<nenums)
                    {
                        res+=-1*nums[i];
                    }
                    else
                    {
                        res += nums[i];
                    }
                }
                int temp = -1*nums[nenums-1];
                if(nenums < nums.size()) temp = (-1*nums[nenums-1]) > nums[nenums] ? nums[nenums] : (-1*nums[nenums-1]);
                res -= temp;
                int a = k-nenums;
                while(a--)
                {
                    temp = -1*temp;
                }
                res+=temp;
            }
            else
            {
                for(int i = 0;i<nums.size();i++)
                {
                    if(i<k)
                    {
                        res += -1*nums[i];
                    }
                    else{
                        res += nums[i];
                    }
                }
            }
        }

        return res;
    }
};

代码随想录中给出了另外一种方法,不用考虑这么多情况,即按绝对值排序,然后遇到负数翻转,并记录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--;
                nums[i] *= -1;
            }
        }
        if(k%2 == 1) 
        {
            nums[nums.size()-1] *= -1;
        }
        int res = 0;
        for(int i=0;i<nums.size();i++)
        {
            res += nums[i];
        }
        return res;
    }
};

134.加油站

文档讲解:代码随想录
视频讲解: 贪心算法,得这么加油才能跑完全程!LeetCode :134.加油站
状态

局部最优:一个连续区间内的省油量之和大于0,说明一定可以在这个区间循环,如果小于0,那么就需要更新区间的起点重新计算。

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        //记录当前这个区间的剩油量
        int curres = 0;
        //记录整个数组的剩油量
        int totalres = 0;
        //需要更新的起始点
        int res = 0;
        for(int i=0;i<gas.size();i++)
        {
            curres += gas[i]-cost[i];
            totalres += gas[i]-cost[i];
            //当这个区间的剩油量小于0,舍去更新res
            if(curres < 0)
            {
                res = i+1;
                curres = 0;
            }
        }
        if(totalres < 0)
        {
            return -1;
        }
        return res;
    }
};

135.分发糖果

文档讲解:代码随想录
视频讲解: 贪心算法,两者兼顾很容易顾此失彼!LeetCode:135.分发糖果
状态

考虑左右对中间的影响,可以先考虑一边,在考虑另一边时,增加判断即可
对于这道题,可以先只考虑当前孩子的评分比左边孩子高的情况,那么就是左边孩子的糖果数+1.
接着考虑当前孩子的评分比右边孩子高的情况,同样是右边孩子的糖果数+1,但由于之前有左边孩子的影响,为了满足左右两边孩子的共同影响,应当选择两个结果的最大值

//i+1 比 i 大那么就增加一个糖果
//i-1比i 大 那么也增加一个糖果
class Solution {
public:
    int candy(vector<int>& ratings) {
        //首先初始化糖果数组全为1
        vector<int> candy(ratings.size(),1);

        //先考虑右边孩子比左边大的情况 比较当前位置和其左边位置
        //如果大,那么就加1
        for(int i=1;i<ratings.size();i++)
        {
            if(ratings[i-1]< ratings[i])
            {
                candy[i] = candy[i-1]+1;
            }
        }
        //再考虑左边孩子比右边大的情况 比较当前位置和其右边位置
        //从后向前
        //由于此时已经存在右边比左边大的结果,如果大,那么结果应当为右边的结果+1,
        //当然当前这个位置还存在一个结果,那么应当取这两个的最大值
        for(int i = ratings.size()-2;i>=0;i--)
        {
            if(ratings[i+1]<ratings[i])
            {
                int temp = candy[i+1]+1;
                candy[i] = max(candy[i],temp);
            }
        }

        int res = 0;
        for(int i = 0;i<candy.size();i++)
        {
            res += candy[i];
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值