LeetCode check-in day35 greedy algorithm for distributing candies, gas stations


knowledge summary

Greedy algorithm continues, many ideas are very ingenious, but there is no template, so we can only do more and more practice, usually after doing it once.


Leetcode 1005. Maximized Array Sum After K Inversions

topic link

topic description

Given an array of integers nums and an integer k, modify the array as follows:

Select an index i and replace nums[i] with -nums[i].
Repeat this process exactly k times. The same subscript i can be selected multiple times.

After modifying an array in this way, return the largest sum possible for the array .
insert image description here

code description

使用PriorityQueue 来实现最小堆, 每次都将最小的数取负数再求和

class Solution {
    
    
    public int largestSumAfterKNegations(int[] nums, int k) {
    
    
        // PriorityQueue queue = new PriorityQueue<>((a1, a2) -> a1-a2);
        Queue<Integer> minH = new PriorityQueue<>();
        int sum = 0;
        for(int num : nums){
    
    
            minH.add(num);
            sum += num;
        }
        while(k > 0 && !minH.isEmpty()){
    
    
            int minNum = minH.poll();
            sum = sum - 2 * minNum;
            minH.offer(-minNum);
            k--;
        }
        return sum;
    }
}

Leetcode 134. Gas Station

topic link

topic description

There are n gas stations on a loop, and the i-th gas station has gas[i] liters of gasoline.

You have a car with unlimited fuel tank capacity, and it takes cost[i] liters of gasoline to drive from the i-th gas station to the i+1-th gas station. You start off from one of the gas stations, starting with an empty tank.

Given two integer arrays gas and cost, return the number of the gas station at the time of departure if you can drive around the circle in order, otherwise return -1. If a solution exists, it is guaranteed to be unique.

insert image description here

code description

The idea is very ingenious. To sum it up in one sentence, I record the accumulated fuel volume. Once the accumulated fuel volume is less than 0, it means that the previous gas station cannot be used as a starting point, and start again from the next stop of i+1.

class Solution {
    
    
    public int canCompleteCircuit(int[] gas, int[] cost) {
    
    
        int totalSum = 0, curSum = 0;
        int start  = 0;
        for(int i = 0; i < gas.length; i++){
    
    
            curSum += gas[i] - cost[i];
            totalSum += gas[i] -cost[i];
            if(curSum < 0){
    
    
                start = (i+1) % cost.length;
                curSum = 0;
            }
        }
        if(totalSum < 0) return -1; // 总消耗> 总获取,返回-1
        return start;
    }
}

Leetcode 135. Distribute Candy

topic link

topic description

n children stand in a row. You are given an integer array ratings representing each child's rating.

You need to distribute candy to these children according to the following requirements:

Each child is assigned at least 1 candy.
The child with the higher score of two adjacent children gets more candies.
Please distribute candies to each child, calculate and return the minimum number of candies that need to be prepared.
insert image description here

code description

algorithm:

  1. First traverse from left to right, if the right side is larger than the left side, add 1;
  2. Then traverse from right to left, if the left is larger than the right, and the left of candyNum is less than or equal to the right, take the maximum value of the two + 1, the traversal process can be seen in the following figure:

insert image description here

class Solution {
    
    
    public int candy(int[] ratings) {
    
    
        int[] candyNum = new int[ratings.length];
        Arrays.fill(candyNum, 1);
        
        // from left to right
        // if right one is larger than left one, candyNum + 1
        for(int i = 1; i < ratings.length; i++){
    
    
            if(ratings[i] > ratings[i-1]){
    
    
                candyNum[i] = candyNum[i-1] + 1;
            }
        }

        // from right to left
        for(int i = ratings.length -2; i>=0; i--){
    
    
            if(ratings[i] > ratings[i+1] && candyNum[i] <= candyNum[i+1]){
    
    
                candyNum[i] = Math.max(candyNum[i], candyNum[i+1]) + 1;
            }
        }

        int res = 0;
        for(int num : candyNum){
    
    
            res += num;
        }
        return res;

    }
}

Guess you like

Origin blog.csdn.net/weixin_45872648/article/details/131180016