代码随想录-2023/08/01

93 阅读1分钟

贪心算法

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

解题思路:

  1. 每次把最小值取反即能够构成最大数组和
  2. 因为若最小值是负数, 则其相反数就为正数, 最大利益化
  3. 若最小值是正数, 则其相反数是最小负数, 损失最小化

代码:

class Solution {
    public int largestSumAfterKNegations(int[] nums, int k) {
        // 每次把最小的前面加个负号即可
        // 动态的求数组的最大值或最小值---小顶堆
        PriorityQueue<Integer> queue = new PriorityQueue<>();
        for(int i:nums){
            queue.offer(i);
        }

        for(int i=0; i<k; i++){
            int min = queue.poll();
            queue.offer(-min);
        }

        int sum = 0;
        for(int num:queue){
            sum += num;
        }
        return sum;
    }
}

134.加油站

解题思路:

  1. 不断计算当前位置的剩余油量, 当遇到花费最多处, 那么最小剩余油量的下一个位置即是最佳开始的地方

代码:

class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        int n = cost.length;
        int spare = 0; 
        int minIndex = 0;
        int minSpare = Integer.MAX_VALUE;
        for(int i=0; i<n; i++){
            spare += gas[i] - cost[i];
            if(spare <= minSpare){
                minSpare = spare;
                minIndex = i;
            }
        }
        return spare < 0 ? -1 : (minIndex+1)%n;
       
    }
}

135.分发糖果

解题思路:

  1. 先从左到右, 再从右到左, 鱼和熊掌不能兼得

代码:

class Solution {
    public int candy(int[] ratings) {
        int len = ratings.length;
        int[] candy = new int[len];
        candy[0] = 1;
        // 1.从前向后处理
        for (int i = 1; i < len; i++) {
            candy[i] = (ratings[i] > ratings[i - 1]) ? candy[i - 1] + 1 : 1;
        }
        // 2.从后向前处理
        for (int i = len - 2; i >= 0; i--) {
            if (ratings[i] > ratings[i + 1]) {
                candy[i] = Math.max(candy[i], candy[i + 1] + 1);
            }
        }


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