• 海智算法训练营第三十三天 | 第八章 贪心算法 part03 | ● 1005.K次取反后最大化的数组和 ● 134. 加油站● 135. 分发糖果


     今日任务:

    1.k次取反后最大化数组和

    2.贪心解决加油站问题

    3.左右边界分别处理——分发糖果

    1.k次取反后最大化数组和

    力扣题目链接

    这道题比较简单就不多说了。

    1. class Solution {
    2. public int largestSumAfterKNegations(int[] nums, int k) {
    3. Arrays.sort(nums);
    4. for (int i = 0; i < nums.length && nums[i] < 0 && k > 0; i++) {
    5. nums[i] = -nums[i];
    6. k--;
    7. }
    8. Arrays.sort(nums);
    9. if(k % 2 == 1) nums[0] = -nums[0];
    10. int sum = Arrays.stream(nums).sum();
    11. return sum;
    12. }
    13. }

    2.贪心解决加油站问题

    力扣题目链接

    题目要求: 

    这是此题的贪心解法,先把每个站点总需要花费的油量计算出来,如果所有油量加起来是小于零的那么不管怎样都是不能转一圈的。

    这道题可以这样理解,找到curSum的最小值从该最小值的后一个值开始走就对了,理解成,你需要在前面累积最多的油量,给这个消耗最多的点去用。

    1. class Solution {
    2. public int canCompleteCircuit(int[] gas, int[] cost) {
    3. int curSum = 0 , totalSum = 0 , start = 0;
    4. for (int i = 0; i < gas.length; i++) {
    5. curSum += gas[i] - cost[i];
    6. totalSum += gas[i] - cost[i];
    7. if (curSum < 0){
    8. start = i+1;
    9. curSum = 0;
    10. }
    11. }
    12. if (totalSum < 0) return -1;
    13. return start;
    14. }
    15. }

    此外另外一种方法也很好理解但是不是贪心的算法:

    1. class Solution {
    2. public int canCompleteCircuit(int[] gas, int[] cost) {
    3. int sum = 0;
    4. int min = 0;
    5. for (int i = 0; i < gas.length; i++) {
    6. sum += (gas[i] - cost[i]);
    7. min = Math.min(sum, min);
    8. }
    9. if (sum < 0) return -1;
    10. if (min >= 0) return 0;
    11. for (int i = gas.length - 1; i > 0; i--) {
    12. min += (gas[i] - cost[i]);
    13. if (min >= 0) return i;
    14. }
    15. return -1;
    16. }
    17. }

    直接从全局进行贪心选择,情况如下:

    • 情况一:如果gas的总和小于cost总和,那么无论从哪里出发,一定是跑不了一圈的

    • 情况二:rest[i] = gas[i]-cost[i]为一天剩下的油,i从0开始计算累加到最后一站,如果累加没有出现负数,说明从0出发,油就没有断过,那么0就是起点。

    • 情况三:如果累加的最小值是负数,汽车就要从非0节点出发,从后向前,看哪个节点能把这个负数填平,能把这个负数填平的节点就是出发节点。(主要是这里,从后往前遍历和负数进行抵消)

    3.左右边界分别处理——分发糖果

    力扣题目

    题目描述:

    首先创建数组,给每个位置都赋值为1,先看左边,从左到右如果右边的数比左边大,那么就+1,再看右边,从右到左,如果左边比右边大,那么这时候如果想要满足左边又满足右边的条件的话那就需要选取当前的最大值,这样才不会冲突。

    看评论有个比较好理解的说法:两种情况要同时满足,原先小的糖果数我就可以满足,我更大的糖果数怎么就满足不了了呢?

    1. class Solution {
    2. public int candy(int[] ratings) {
    3. int res[] = new int[ratings.length];
    4. Arrays.fill(res,1);
    5. for (int i = 1; i < ratings.length; i++) {
    6. if(ratings[i] > ratings[i-1]){
    7. res[i] = res[i-1] + 1;
    8. }
    9. }
    10. for (int i = ratings.length-2; i >= 0; i--) {
    11. if(ratings[i] > ratings[i+1]){
    12. res[i] = Math.max(res[i] , res[i+1] + 1);
    13. }
    14. }
    15. return Arrays.stream(res).sum();
    16. }
    17. }

    学习时长:2h

    总结:此次学习贪心如何解决区间问题,以及遇到需要左右判断的题目怎么去逐一分开去做。

  • 相关阅读:
    css第八课:文本属性(字体,颜色属性)
    java计算机毕业设计菲特尼斯健身管理系统设计与实现MyBatis+系统+LW文档+源码+调试部署
    贪心算法学习
    数据预处理方法
    【记录】软件自动修复工具Jaid配置、调试、运行及相关问题的解决方案
    GMAN: A Graph Multi-Attention Network for Traffic Prediction(2020AAAI)
    .net webapi 实现 接口版本控制并打通swagger支持
    单片机控制直流电机(风扇)电路详解
    ‘vue‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件 出现这个问题如何解决
    day1- day6
  • 原文地址:https://blog.csdn.net/qq_74462324/article/details/136309952