力扣135-分发糖果

148 阅读2分钟

分糖果.png

题目描述

nn个孩子站成一排。给你一个整数数组ratingsratings表示每个孩子的评分。 你需要按照以下要求,给这些孩子分发糖果:

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

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

用例

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

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

题目分析

刷高畅大佬的leetcode101遇到的题,它是最值问题,一般可能考贪心,但仍没想到如何处理(既要考虑左侧,又要考虑右侧....),特此记录一番,以便后续再刷。 该问题要根据相邻孩子的评分,分配最少糖果数目。

如果仅仅考虑孩子与后一个孩子的评分,问分配最少糖果数目。那么我们只需从左往右遍历一次,如果后一位同学比前一位同学评分高,那么后一位同学糖果数是前一位同学糖果数目加11,否则糖果数为11(以保证最少糖果数)。

但是,这只能保证同学与后一同学的糖果满足条件,忽略了同学与前一同学糖果上的约束。那么如果我们从右往左遍历一次,便可以保证同学与前一同学糖果上的约束了(需要注意,从右往左遍历的时候,不要破坏先满足的约束)。

这题目是一道贪心问题,难点是需要考虑两侧同学以满足糖果上的约束(相邻同学评分高,糖果多)并求最少糖果数。局部贪心是让单侧同学先满足糖果上的约束并求最少糖果数。那为什么局部最优能保证全局最优呢?直观上,如果存在更少的糖果数,那么必然有一位同学多分了糖果,但是,这种情况显然不存在的。

代码

class Solution {
public:
    int candy(vector<int>& ratings) {
        vector<int> num(ratings.size(), 1);
        int count= 0;
		for(int i= 1; i< ratings.size(); i++){
        	if(ratings[i]> ratings[i- 1]){num[i]= num[i- 1]+ 1;}
        }
        for(int j= ratings.size()- 2; j>= 0; j--){
        	if(ratings[j]> ratings[j+ 1]){num[j]= (num[j+ 1]+ 1> num[j]? num[j+ 1]+ 1: num[j]);}
        	count+= num[j];
        }
        count+= num[ratings.size()- 1];
        return count;
    }
};

其中,时间复杂度T(n)=O(n)T(n)= O(n).