LeetCode分发糖果(贪心思路分析)

题目描述

LeetCode分发糖果(贪心思路分析)_第1张图片

LeetCode分发糖果(贪心思路分析)_第2张图片

贪心思路


思路及解法

我们可以将「相邻的孩子中,评分高的孩子必须获得更多的糖果」这句话拆分为两个规则,分别处理。

左规则:当 ratings[i−1]

右规则:当 ratings[i]>ratings[i+1] 时,i 号学生的糖果数量将比 i+1 号孩子的糖果数量多。

我们遍历该数组两次,处理出每一个学生分别满足左规则或右规则时,最少需要被分得的糖果数量。每个人最终分得的糖果数量即为这两个数量的最大值。

具体地,以左规则为例:我们从左到右遍历该数组,假设当前遍历到位置 i,如果有 ratings[i−1]

在实际代码中,我们先计算出左规则 left 数组,在计算右规则的时候只需要用单个变量记录当前位置的右规则,同时计算答案即可。

作者:力扣官方题解

我们怎么知道,这两个规则得出来的结果,就能得出正确的答案呢?

首先满足左规则的情况下:

1 .只有当右边的数比左边的数大的时候右边的数始终比左边的数大1。

2. 当ratings[i]的数比ratings[i-1]的数小于等于的时候,此时所有的candies[i]都是1 

满足右规则:

3. ratings[i] > ratings[i+1]时,candies[i]始终比candies[i+1]大1。

4. ratings[i] <= ratings[i+1]时, 这时候为了满足右规则和左规则,比较1和candies[i]取最大值来同时满足右边和左边。

class Solution {
public:
    int candy(vector& ratings) {
        vector candyVec(ratings.size(), 1);
        // 从前向后
        for (int i = 1; i < ratings.size(); i++) {
            if (ratings[i] > ratings[i - 1]) candyVec[i] = candyVec[i - 1] + 1;
        }
        // 从后向前
        for (int i = ratings.size() - 2; i >= 0; i--) {
            if (ratings[i] > ratings[i + 1] ) {
                candyVec[i] = max(candyVec[i], candyVec[i + 1] + 1);
            }
        }
        // 统计结果
        int result = 0;
        for (int i = 0; i < candyVec.size(); i++) result += candyVec[i];
        return result;
    }
};

时间复杂度O(N)

空间复杂度O(N)

举例,关键步骤是同时满足左右两边,取最大值!

        ·                         ratings数组(上)左规则,右规则,candies数组(最下)
 

1 2 87 87 87 2 1
1 2 3 1 1 1 1
1 1 1 1 3 2 1
1 2 3 1 3 2 1

你可能感兴趣的:(贪心算法,leetcode,算法,贪心算法,c++)