leetcode
leetcode 101 ~ 150
分发糖果

分发糖果

难度:

标签:

题目描述

n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。

你需要按照以下要求,给这些孩子分发糖果:

  • 每个孩子至少分配到 1 个糖果。
  • 相邻两个孩子评分更高的孩子会获得更多的糖果。

请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目

 

示例 1:

输入:ratings = [1,0,2]
输出:5
解释:你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。

示例 2:

输入:ratings = [1,2,2]
输出:4
解释:你可以分别给第一个、第二个、第三个孩子分发 1、2、1 颗糖果。
     第三个孩子只得到 1 颗糖果,这满足题面中的两个条件。

 

提示:

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

代码结果

运行时间: 32 ms, 内存: 18.2 MB


/*
 * 思路:
 * 1. 首先初始化每个孩子至少得到1个糖果。
 * 2. 从左到右遍历,如果右边的孩子评分比左边的高,右边孩子的糖果数为左边孩子糖果数加1。
 * 3. 从右到左遍历,如果左边的孩子评分比右边的高,左边孩子的糖果数为右边孩子糖果数加1。
 * 4. 使用Java Stream返回所有孩子糖果数的总和。
 */
 
import java.util.*;
import java.util.stream.*;
 
public class Solution {
    public int candy(int[] ratings) {
        int n = ratings.length;
        int[] candies = new int[n];
        Arrays.fill(candies, 1);
 
        // 从左到右遍历
        IntStream.range(1, n).forEach(i -> {
            if (ratings[i] > ratings[i - 1]) {
                candies[i] = candies[i - 1] + 1;
            }
        });
 
        // 从右到左遍历
        IntStream.iterate(n - 2, i -> i >= 0, i -> i - 1).forEach(i -> {
            if (ratings[i] > ratings[i + 1]) {
                candies[i] = Math.max(candies[i], candies[i + 1] + 1);
            }
        });
 
        // 计算总糖果数
        return Arrays.stream(candies).sum();
    }
}
 

解释

方法:

该题解采用了两次遍历的方式来分配糖果。首先从左到右遍历,保证相邻两个孩子中评分更高的孩子获得更多的糖果。然后从右到左遍历,再次保证相邻两个孩子中评分更高的孩子获得更多的糖果,同时不破坏之前的分配。最后计算总共需要的糖果数目。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
为什么在解决这个问题时需要两次遍历(一次从左到右,一次从右到左),单次遍历是否能够满足题目要求?
单次遍历无法确保同时满足左右两边孩子之间评分与糖果数的关系。例如,从左到右遍历时,我们确保每个孩子与其左边的孩子评分较高时获得更多糖果。但这种方式可能忽略了右边孩子的评分情况,导致评分高的孩子糖果数不足。因此,需要从右到左再进行一次遍历,以保证右边的孩子如果评分更高也能获得更多糖果。两次遍历确保了无论是左边还是右边的孩子,只要评分更高,就能获得更多糖果。
🦆
在第二次遍历过程中,使用`max`函数来更新糖果数的原理是什么?这样做为何能保证不破坏第一次遍历的结果?
第二次遍历使用`max`函数是为了确保在满足从右到左的孩子评分更高获得更多糖果的同时,不破坏第一次遍历对左边孩子评分更高时的糖果分配。`max`函数确保如果第一次遍历给出的糖果数已经足够,就保持不变;如果不足,则进行更新,以适应右边邻居的评分。这样,我们既保持了第一次遍历的结果,也满足了新的条件。
🦆
算法中初始化所有孩子的糖果数为1的依据是什么?这一步是否有可能导致某些情况下的糖果分配不公平?
初始化所有孩子的糖果数为1是基于至少每个孩子需要获得一颗糖果的最基本需求。这是问题的基本条件,保证每个孩子至少有糖果。这种初始化本身不会导致不公平,因为之后的两次遍历过程会根据孩子之间的评分差异调整糖果数,以确保评分较高的孩子获得更多糖果。
🦆
如果数组`ratings`是单调递增或递减的,这种双遍历方法的效率如何?是否有更优的方法?
对于单调递增或递减的`ratings`数组,这种双遍历方法仍然有效,但效率不是最优的。例如,在单调递增的数组中,一次从左到右的遍历就足以解决问题,因为每个后续的孩子评分都比前一个高,只需逐个增加糖果数即可;同理,单调递减的数组只需一次从右到左的遍历。尽管这样,使用双遍历方法在任何情况下都是安全的,保证了解决方案的正确性,但在已知数组单调性的情况下,可以采用单次遍历以提升效率。

相关问题