Day34——K次取反后最大化的数组和、加油站、分发糖果

简介: Day34——K次取反后最大化的数组和、加油站、分发糖果

前言


思念折腾人,也锻炼人,更锻造人的性格的沉稳和感情的深沉。思念别人是一种温馨,被人思念是一种幸福

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


力扣

1、暴力思路:


在k还没有用完前,每次选择最小的元素,把它取反,这样就能得到最大的和。

class Solution {
public:
    int largestSumAfterKNegations(vector<int>& nums, int k) {
    while(k--)                    //记录K的次数
        {
            int min=1e8;            
            int j=0;
            for(int i=0;i<nums.size();i++)
            {
        if(nums[i]<min)            //找出最小值
                {
          min=nums[i];
                    j=i;
                }
            }
            nums[j]=-nums[j];        //反
        }
        int sum=0;
        for(int i=0;i<nums.size();i++)        //记录和
        {
            printf("%d ",nums[i]);
      sum+=nums[i];
        }
        return sum;
    }
};

但这是时间复杂度比较大的解法,我们还可以改善一下。

2、贪心思路:


要先和最大。

1、把负数全部变成正数。

2、如果全是正数,把最小的正数变成负数。

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 i=0;
        for(i=0;i<nums.size();i++)            
        {
            if(nums[i]<0)                    //负数都反
            {
                nums[i]=-nums[i];
                k--;
            }
            if(k==0)                //用完了就退出了
            {
                break;
            }
        }
        if(k%2==1)                    //剩余的看单双数,双数等于不变
        {
            nums[nums.size()-1]*=-1;        //末尾最小
        }
        int sum=0;
        for(auto it:nums)
        {
            sum+=it;
        }
        return sum;
    }
};

二、加油站


力扣

在一条环路上有 n 个加油站,其中第 i 个加油站有汽油 gas[i] 升。

你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。

给定两个整数数组 gas 和 cost ,如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1 。如果存在解,则 保证 它是 唯一 的。

1、贪心思路1:


在确定了是可以跑一圈的情况下,在中间出现了负值,说明从0到负值位置开始是行不通的,要从后面往前,找到那个可以补缺的点哪里。

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int min=1e8;
        int sum=0;
    for(int i=0;i<gas.size();i++)
        {
            sum+=gas[i]-cost[i];            //从0开始跑计算总油量
      if(sum<min)
            {
                min=sum;            //记录最小的负值
            }
        }
        if(sum<0)        //小于0就退出,因为不可能跑一圈了
        {
            return -1;
        }
            if(min>=0)        //如果从0开始跑可以跑一圈就返回0
        {
          return 0;
        }
        for(int i=gas.size()-1;i>=0;i--)    //从后往前遍历
        {
            min+=gas[i]-cost[i];        //啥时候可以填补空缺
            if(min>=0)
            return i;
        }
        return -1;
    }
};

2、贪心思路2:


如果cursum小于0了,那么【0,i】上面开始都是不行的。

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) {   // 当前累加rest[i]和 curSum一旦小于0
                start = i + 1;  // 起始位置更新为i+1
                curSum = 0;     // curSum从0开始
            }
        }
        if (totalSum < 0) return -1; // 说明怎么走都不可能跑一圈了
        return start;
    }
};

三、分发糖果


力扣

class Solution {
public:
    int candy(vector<int>& ratings) {
        vector<int> candys(ratings.size(),1);
        for(int i=1;i<ratings.size();i++)        //右孩子大于左孩子
        {
            if(ratings[i]>ratings[i-1])
            {
                candys[i]=candys[i-1]+1;        //比旁边的孩子多一个
            }
        }
        for(int i=ratings.size()-2;i>=0;i--)        //重点,重后往前
        {
            if(ratings[i]>ratings[i+1])
            {
                candys[i]=max(candys[i],candys[i+1]+1);
            }
        }
        int sum=0;
        for(auto it:candys)
        sum+=it;
        return sum;
    }
};

为什么要从后往前呢,从后往前,我们可以用处理过的结果来判断,因为前一个是处理过的,从前往后,就是依据前一个判断后一个,前一个都是没有处理过的。

总结


贪心没有套路,只有一点感觉,继续加油哇。

相关文章
|
6月前
|
算法 测试技术
枚举(蓝桥练习)(反倍数、特别数的和、找到最多的数、小蓝的漆房、小蓝和小桥的挑战)
枚举(蓝桥练习)(反倍数、特别数的和、找到最多的数、小蓝的漆房、小蓝和小桥的挑战)
|
算法 测试技术 C++
C++算法:分发糖果
C++算法:分发糖果
|
6月前
|
算法 C语言
(“拨”取数字的典例:N位水仙花数判断及水仙花数变种)
这篇内容介绍了如何判断和生成水仙花数,水仙花数是一个n位数,其各位数字的n次方之和等于该数本身。文章首先回顾了"拨数"的概念,然后通过实例展示了如何判断三位水仙花数,并将其推广到任意位数的水仙花数。作者提供了详细的解题思路和代码示例,强调了解决这类问题时要慢下来,分步骤分析问题。最后,文章还探讨了一个水仙花数的变种问题,即数字拆分后乘积之和等于原数的情况。
158 0
|
6月前
|
算法 测试技术 C#
【树上倍增】【内向基环树】【 图论 】2836. 在传球游戏中最大化函数值
【树上倍增】【内向基环树】【 图论 】2836. 在传球游戏中最大化函数值
|
6月前
|
人工智能 算法
前缀和算法题(区间次方和、小蓝平衡和、大石头的搬运工、最大数组和)
前缀和算法题(区间次方和、小蓝平衡和、大石头的搬运工、最大数组和)
|
算法
【算法挨揍日记】day06——1004. 最大连续1的个数 III、1658. 将 x 减到 0 的最小操作数
1004. 最大连续1的个数 III 题目描述: 给定一个二进制数组 nums 和一个整数 k,如果可以翻转最多 k 个 0 ,则返回 数组中连续 1 的最大个数 。
406 1
|
12月前
|
算法 网络架构
代码随想录算法训练营第三十三天 | LeetCode 1005. K 次取反后最大化的数组和、134. 加油站、135. 分发糖果
代码随想录算法训练营第三十三天 | LeetCode 1005. K 次取反后最大化的数组和、134. 加油站、135. 分发糖果
55 0
数列中,第一项为3,后一项都比前一项的值增5。下列给定程序中,函数fun的功 能是:计算前n(4≤n≤50)项的累计和。在累加过程中把那些被4除后余2的当前累 加值放入数组中
数列中,第一项为3,后一项都比前一项的值增5。下列给定程序中,函数fun的功 能是:计算前n(4≤n≤50)项的累计和。在累加过程中把那些被4除后余2的当前累 加值放入数组中
算法训练Day34|1005.K次取反后最大化的数组和 ● 134. 加油站● 135. 分发糖果
算法训练Day34|1005.K次取反后最大化的数组和 ● 134. 加油站● 135. 分发糖果