算法训练营第三十四天|1005.K次取反后最大化的数组和、134. 加油站、135. 分发糖果

52 阅读1分钟

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

class Solution {
    public int largestSumAfterKNegations(int[] nums, int k) {
        Arrays.sort(nums);
        int i = 0;
        // 把尽可能多的负数都翻转为正数
        while(k > 0 && i < nums.length && nums[i] < 0){
            nums[i] = -nums[i];
            k--;
            i++;
        }

        if(k == 0){
            return Arrays.stream(nums).sum();
        }
        else{ // k != 0 
            Arrays.sort(nums); // 此时只有非负整数
            // 判断剩余翻转次数是否为奇数, 如果是奇数则将第一个元素翻转(最小正数变负数, 对最终结果影响最"小")
            if(k % 2 != 0)nums[0] = -nums[0];
            // 如果剩余翻转次数为偶数,只对第一个元素翻转偶数次,等于什么都没做
        }
        
        return Arrays.stream(nums).sum();
    }
}

134. 加油站

class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        int totalGas = 0;
        int totalCost = 0;
        int start = 0;
        int remain = 0;
        for(int i = 0; i < gas.length; i++){
            totalGas += gas[i];
            totalCost += cost[i];
            remain += gas[i] - cost[i];
            if(remain < 0){
                start = i + 1;
                remain = 0;
            }
        }
        if(totalGas < totalCost){
            return -1;
        }
        else return start;
    }
}

135. 分发糖果

class Solution {
    public int candy(int[] ratings) {
        int n = ratings.length;
        int[] candies = new int[n];

        Arrays.fill(candies, 1);

        for(int i = 1; i < n; i++){
            if(ratings[i] > ratings[i - 1]){
                candies[i] = candies[i - 1] + 1;
            }
        }

        for(int i = n - 2; i >= 0; i--){
            if(ratings[i] > ratings[i + 1]){
                // 孩子i的candies[i]来自于他先比他的左孩子多,然后再和右孩子比谁多,最后在两者间取最大,得到局部最优。
                candies[i] = Math.max(candies[i], candies[i + 1] + 1);
            }
        }

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