【C++编程能力提升】

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

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

核心:要求取反后的数组和最大,也就是取反的元素最好是负数,没有负数的情况下必须是最小的正数(包括0)。
首先,原数组按照绝对值从大到小排列;
然后,遍历数组元素,没遇到负数则将其取反,同时k–;
接着,遍历完所有元素后,k仍大于0需要对最小正数反复取反,若k是偶数由于可以反复取反,实质与不操作没有区别,因此只有k(剩余的k)是奇数时,对最小整数取一次反即可。
最后,统计数组和。

    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);  //nums元素按绝对值从大到小排列
        for(int i=0;i<nums.size();++i)
        {//遍历数组元素,遇到负数则变为正数,同时k--
            if(nums[i]<0 && k>0)
            {
                nums[i]*=-1;
                k--;
            }
        }
        //处理完数组中所有负数后k仍大于0,需要对最小的正数(包括0)反复变为负数
        if(k%2==1)
            nums[nums.size()-1]*=-1;    //k为偶数可反复对最小正数操作,相当于没有操作
        int res=0;
        for(int num:nums)
            res+=num;
        return res;
    }

二、134 加油站

题目链接:134 加油站

核心:建模成剩余汽油gas-cost的问题会简单很多,如果全部的剩余汽油都小于0那么肯定无法环路行驶;否则一定可以环路行驶,只需找到起始位置start即可。
如果从start开始统计剩余汽油和,环路的整个区间内都大于等于0,说明start就是起始位置,也就是说一旦某区间的剩余汽油和小于0,说明从此处开始不能环路行驶,需要更新起始位置。(起始位置必然存在的前提是:全部的剩余汽油和大于等于0)

    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        //贪心算法:统计每个元素的gas-cost,一旦某区间累加和小于0,则更新起始位置
        int start=0;    //记录更新后的起始位置
        int total=0;    //记录所有元素的gas-cost
        int curSum=0;   //记录从i开始某一区间的累加和
        for(int i=0;i<gas.size();++i)
        {
            total+=gas[i]-cost[i];
            curSum+=gas[i]-cost[i];
            if(curSum<0)
            {
                start=i+1;  //更新区间起点,直到从start开始的某区间累加和大于等于0
                curSum=0;   //重新统计区间元素和
            }
        }
        if(total<0)
            return -1;  //剩余总和小于说明一定不存在起始位置,否则一定存在起始位置,即start
        return start;
    }

三、135 分发糖果

题目链接:135 分发糖果

核心:使用2次贪心策略,第一次从前往后遍历,比较右孩子是否大于左孩子,若大于则右孩子比左孩子多一个糖果;第二次从后往前遍历,比较左孩子是否大于右孩子,若大于则左孩子需要更新,要么比右孩子多一个糖果,要么仍沿用第一次遍历得到的左孩子,取其最大值同时满足两次贪心策略。

    int candy(vector<int>& ratings) {
        //2次贪心策略:从前往后比较右孩子是否大于左孩子,从后往前比较左孩子是否大于右孩子
        vector<int> candynum(ratings.size(),1); //定义初始化存放每个小孩的糖果的数组
        //从前往后遍历,比较右孩子是否大于左孩子
        for(int i=1;i<ratings.size();++i)
        {
            if(ratings[i]>ratings[i-1])
                candynum[i]=candynum[i-1]+1;    //右孩子比左孩子多一个
        }
        //从后往前遍历,比较左孩子是否大于右孩子
        for(int i=ratings.size()-1;i>=1;--i)
        {
            if(ratings[i-1]>ratings[i])
                candynum[i-1]=max(candynum[i]+1,candynum[i-1]);    //左孩子比右孩子多一个,或者从前往后遍历的糖果,取最大值
        }
        int res=0;
        for(int num:candynum)
            res+=num;   //统计糖果数
        return res;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值