Java description LeetCode, 135. Candy distribution

Hello everyone, I'm hehaige and focus on the back end. If I can, I want to be a code designer instead of an ordinary coder to witness the growth of hehaige. Your comments and praise are my biggest driving force. If you have any mistakes, please don't hesitate to comment. Thank you very much. Let's support the original! If there is a clerical error in pure hand typing, please forgive me.

1-1: title

There are n children standing in a line. Each child is assigned a rating value given in the integer array ratings.

You are giving candies to these children subjected to the following requirements:

Each child must have at least one candy.
Children with a higher rating get more candies than their neighbors.
Return the minimum number of candies you need to have to distribute the candies to the children.

Example 1:

Input: ratings = [1,0,2]
Output: 5
Explanation: You can allocate to the first, second and third child with 2, 1, 2 candies respectively.

Example 2:

Input: ratings = [1,2,2]
Output: 4
Explanation: You can allocate to the first, second and third child with 1, 2, 1 candies respectively.
The third child gets 1 candy because it satisfies the above two conditions.

Constraints:

n == ratings.length
1 <= n <= 2 * 104
0 <= ratings[i] <= 2 * 104

Source: LeetCode
Link: https://leetcode-cn.com/problems/candy

1-2: own idea

☘️ My own idea is to traverse once and consider the three positions of I-1, I and I + 1. For example, ratings=[2,1,5] distribute candy=[2,1,2], but if you think about it, you will find that 1 cannot be divided. Therefore, when considering both sides, it must be affected by other factors. This example can well illustrate this problem.

1-2: solution 1

1-2-1: idea

☘️ It's not good to consider both sides at the same time. One way is to consider one side first. If the rating on the right is larger than that on the left, distribute one more candy on the right. In this way, we can ensure that part of the topic is satisfied. As long as you traverse from right to left, if the rating on the left is larger than that on the right, you will allocate one more candy on the left than on the right. However, it should be noted that the value of the second round should not be smaller than the value of the first round, otherwise it will not meet the local optimization of the first round. You can draw a table here to try, and you will understand what I mean. For example, ratings = [1, 2, 2, 5, 4, 3, 2] the first round [1, 2, 1, 2, 1, 1] the second round [1, 2, 1, 4, 3, 2, 1]. Another note is that the same rating does not need more candy, As can be seen from this example, (this is a hidden rule of the topic)

1-2-2: Code

public static int candy(int[] ratings) {
    int n = ratings.length;

    int[] candyDeliver = new int[n];
    for (int i = 0; i < n; i++) {
        candyDeliver[i] = 1;
    }


    for (int i = 1; i < n; i++) {
        // right > left
        if (ratings[i] > ratings[i - 1]) {
            // assert the right child's candy > the left
            candyDeliver[i] = candyDeliver[i - 1] + 1;
        } else {
            // keep one
        }
    }

    for (int i = n - 1; i >= 1; i--) {
        // left > right
        if (ratings[i] < ratings[i - 1]) {
            candyDeliver[i - 1] = Math.max(candyDeliver[i] + 1, candyDeliver[i - 1]);
        } else {
            // keep original to use former result
        }
    }

    System.out.println(Arrays.toString(candyDeliver));

    int sumCandy = 0;
    for (int candy : candyDeliver) {
        sumCandy += candy;
    }
    return sumCandy;
}

1-3: solution 2

1-3-1: idea

☘️ This solution also comes from the answer. He skillfully uses the idea of ascending and descending order to divide an entire array into many small increasing / decreasing arrays, because there must be size between numbers.

1-3-2: Code

    public static int candy2(int[] ratings) {
        int n = ratings.length;
        int ret = 1;
        int inc = 1, dec = 0, pre = 1;
        for (int i = 1; i < n; i++) {
            if (ratings[i] >= ratings[i - 1]) {
                // When the increment occurs, the length of the descending sequence should be reset to 0
                dec = 0;
                // Update the value of pre
                pre = ratings[i] == ratings[i - 1] ? 1 : pre + 1;
                // pre is the candy distributed by the students in this position
                ret += pre;
                // The value of pre is equal to the length of the increment sequence
                inc = pre;
            } else {
                dec++;
                // Why is there this? When the length is equal, the last of the increasing sequence will become a member of the decreasing sequence.
                // For example, the candy added by rating = [1,3,5,3,2,1] is 1,2,3,1,2,4 in turn; Especially in the position of 4, 4 is
                // When dec== inc ==3, I regard the previous 3 as members in descending order, and I myself change from 3 to 4. Although the distribution order does not match
                // The position of the child, but does not affect the total count. The actual distribution should be in the order of [1,2,4,3,2,1].
                if (dec == inc) {
                    dec++;
                }
                ret += dec;
                // pre is only used when incrementing
                pre = 1;
            }
        }
        return ret;
    }

What needs to be explained is in the notes! You can know the process changes in one step debug, or you can compare the problem solutions in the force button.

1-4: summary

☘️ The idea of the answer is unexpected. It can be regarded as a kind of accumulation. Brush more questions. What if you encounter the original question~

Tags: Java Algorithm leetcode

Posted on Sun, 05 Dec 2021 14:30:42 -0500 by megaalf