135. Distribute Candy-Java

The teacher wants to distribute candies to the children. There are N children standing in a straight line, and the teacher will rate each child in advance based on their performance.

You need to help the teacher distribute candies to these children according to the following requirements:

  1. Each child is allocated at least 1 candy.
  2. Among the neighboring children, the child with the higher score must get more candies.

So, how many sweets does the teacher need to prepare at least?

Example 1:
Input: [1,0,2]
Output: 5
Explanation: You can distribute 2, 1, and 2 candies to these three children.

Example 2:
Input: [1,2,2]
Output: 4

Explanation: You can distribute 1, 2, and 1 candy to the three children.
The third child only gets 1 candy, which already meets the above two conditions.

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

Method 1: Violence

  1. The easiest way is to use a one-dimensional array candies to record the number of candies given to students.
  2. First we give each student 1 candy. Then we start scanning the array from left to right.
  3. For each student, if the current rating [i] is higher than the previous student's rating [i-1] , and the number of candies is less than or equal to the previous student cand ies[i]<=candies[i-1] , Then we update candies[i] = candies[i-1] + 1 .
  4. Similarly, we check whether the current student’s rating [i] is higher than the next student’s rating [i+1] , and if so, we also update candies[i] = candies[i+1] + 1 .
    We continue to repeat this step for the ratingsratings array.
  5. If during a certain traversal, the candies array does not change, it means that we have obtained the final candy distribution, and we can stop the traversal at this time.
  6. In order to record whether it has reached the final state, we use flag to record whether there is a change in the number of candies in each traversal. If there is , it is True , otherwise it is False .
public int candy(int[] ratings) {
    
    
    int[] candies = new int[ratings.length];
    Arrays.fill(candies, 1);
    boolean flag = true;
    int sum = 0;
    while (flag) {
    
    
        flag = false;
        for (int i = 0; i < ratings.length; i++) {
    
    
            if (i != ratings.length - 1 && ratings[i] > ratings[i + 1] && candies[i] <= candies[i + 1]) {
    
    
                candies[i] = candies[i + 1] + 1;
                flag = true;
            }
            if (i > 0 && ratings[i] > ratings[i - 1] && candies[i] <= candies[i - 1]) {
    
    
                candies[i] = candies[i - 1] + 1;
                flag = true;
            }
        }
    }
    for (int candy : candies) {
    
    
        sum += candy;
    }
    return sum;
}

Method 2: Use two arrays

  1. In this method, we use two one-dimensional arrays l eft2right and right2left .
    1.1 The array left2right is used to store the number of candies required by each student only related to the left neighbor. That is, the hypothetical rule is: if a student scores higher than the student to his left, then he should get more candy than the student to his left.
    1.2 Similarly, the right2left array is used to store the required number of candies only related to the right neighbor. That is, the hypothetical rule is: if a student scores higher than the student on his right, then he should get more candy than the student on his right.

  2. First, we give each student 1 candy in left2right and right2left . Then, we traverse the entire array from left to right, as long as the current student’s score is higher than his left neighbor, we update the current student’s candy count in the left2right array left2right[i] = left2right[i-1] + 1 , this is because Before each update, the current student’s candy count must be less than or equal to his left neighbor’s candy count.

  3. After scanning from left to right, we use the same method to update right2left[i] to right2left[i] = right2left[i + 1] + 1 from right to left as long as the current student’s score is higher than that of the student on his right .

  4. Now, for the iith student in the array, in order to meet the conditions in the question, we need to give him max(left2right[i],right2left[i]) candy.
    Insert picture description here

public int candy(int[] ratings) {
    
    
	int sum = 0;
	int[] left2right = new int[ratings.length];
	int[] right2left = new int[ratings.length];
	Arrays.fill(left2right, 1);
	Arrays.fill(right2left, 1);
	for (int i = 1; i < ratings.length; i++) {
    
    
	    if (ratings[i] > ratings[i - 1]) {
    
    
	        left2right[i] = left2right[i - 1] + 1;
	    }
	}
	for (int i = ratings.length - 2; i >= 0; i--) {
    
    
	    if (ratings[i] > ratings[i + 1]) {
    
    
	        right2left[i] = right2left[i + 1] + 1;
	    }
	}
	for (int i = 0; i < ratings.length; i++) {
    
    
	    sum += Math.max(left2right[i], right2left[i]);
	}
	return sum;
}

Method 3: Use an array

  1. In the previous method, we used two arrays to record the relationship between each student and his left and right neighbors, and then merged the two arrays. Here we can only use an array candies to record the number of candies allocated to the current student.

  2. First, we give each student 1 candy, then we traverse from left to right and assign candies. We only update the students whose score is higher than the left neighbor and the number of candies is less than or equal to the left neighbor, and update it to candies[i] = candies[ i-1] + 1 .

  3. After traversing from left to right, we also traverse from right to left. Now we need to update each student i to satisfy the relationship between the left neighbor and the right neighbor at the same time. In this traversal summary, if ratings[i]> ratings[i + 1] , we update to candies[i] = max(candies[i], candies[i + 1] + 1]) , so candies[i] At the same time, the constraints of the left neighbor and the right neighbor are satisfied.

public int candy(int[] ratings) {
    
    
	int[] candies = new int[ratings.length];
    Arrays.fill(candies, 1);
    for (int i = 1; i < ratings.length; i++) {
    
    
        if (ratings[i] > ratings[i - 1]) {
    
    
            candies[i] = candies[i - 1] + 1;
        }
    }
    int sum = candies[ratings.length - 1];
    for (int i = ratings.length - 2; i >= 0; i--) {
    
    
        if (ratings[i] > ratings[i + 1]) {
    
    
            candies[i] = Math.max(candies[i], candies[i + 1] + 1);
        }
        sum += candies[i];
    }
    return sum;
}

Guess you like

Origin blog.csdn.net/m0_46390568/article/details/107650967