代码随想录算法训练营第三十四天 _ 贪心算法_1005.K次取反后最大化的数组和、134.加油站、135.分发糖果。

学习目标:

60天训练营打卡计划!

学习内容:

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

  • 本题的策略可分为两次贪心:
    ① 第一次贪心是将所有的负数都变为正数
    ② 第二次贪心是选择牺牲一个最小的数,使其取反直至满足题目的要求取反次数。
  • java中没有使用树数值绝对值对数组排序的api,所以要回忆排序算法
  • 八嘎,我忘记了。。。
  • 插入排序温习

引用自hello算法:https://www.hello-algo.com/chapter_sorting/insertion_sort/
代码随想录算法训练营第三十四天 _ 贪心算法_1005.K次取反后最大化的数组和、134.加油站、135.分发糖果。_第1张图片

class Solution {
    public int largestSumAfterKNegations(int[] nums, int k) {
        // 使用自定义的Comparator对绝对值进行排序
        // 要学会呀。。。
        // Arrays.sort(nums, new Comparator(){
        //     @Override
        //     public int compare(Integer a, Integer b){
        //         return Math.abs(a) - Math.abs(b);
        //     }
        // });
        // 使用插入排序按绝对值大小对数组进行排序
        for (int i = 1; i < nums.length; i++) {
            int key = nums[i];
            int j = i - 1;
            while (j >= 0 && Math.abs(nums[j]) < Math.abs(key)) {
                nums[j + 1] = nums[j];
                j--;
            }
            nums[j + 1] = key;
        }

        for(int i = 0; i < nums.length; i++){
            if(nums[i] < 0 && k > 0){
                nums[i] *= -1;
                k--;
            }    
        }
        if(k % 2 == 1)    nums[nums.length - 1] *= -1;

        return Arrays.stream(nums).sum();
    }
}

134.加油站

  • 不理解这个为什么是贪心算法,确实很难想。
  • 操作非常的巧妙:通过使用for循环从头开始计数可以避免对数组进行环的操作
class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        int start = 0;
        int curGas = 0;
        int totalGas = 0;
        // 使用for循环从头开始计数可以避免对数组进行环的操作
        for(int i = 0; i < gas.length; i++){
            curGas += gas[i] - cost[i];
            totalGas += gas[i] - cost[i];
            // 局部贪心就是这一段的净油量大于0
            if(curGas < 0){
                start = i + 1;
                curGas = 0;
            }  
        }
        if(totalGas < 0)  return -1;
        return start;
    }
}

135.分发糖果

  • 这个题目的精髓在于分别处理比左边大和比右边大,从两次的结果中取出最大的结果。
  • 不懂为什么是贪心算法,迷茫。。。
class Solution {
    public int candy(int[] ratings) {
        int size = ratings.length;
        int[] res = new int[size];
        res[0] = 1;
        for(int i = 1; i < size; i++){
            res[i] = 1;
            // 从左向右比,大于左边则加1.
            if(ratings[i] > ratings[i-1]){
                res[i] = res[i-1] + 1;
            }
        }
        for(int i = size - 2; i >= 0; i--){
            // 从右向左比,大于右则加1.
            if(ratings[i] > ratings[i+1]){
                res[i] = Math.max(res[i], res[i+1] + 1);
            }
        }
        return Arrays.stream(res).sum();
    }
}

学习时间:

  • 上午两个小时,整理文档半小时。

你可能感兴趣的:(刷题训练心得,算法,贪心算法,python)