来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/candy
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
135.老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。你需要按照以下要求,帮助老师给这些孩子分发糖果:每个孩子至少分配到 1 个糖果。评分更高的孩子必须比他两侧的邻位孩子获得更多的糖果。那么这样下来,老师至少需要准备多少颗糖果呢?
这是一个困难题,只能求助题解。题解使用两次遍历来解题,第一次遍历考虑右边孩子比左边孩子高分的情况,第二次遍历考虑左边孩子比右边孩子高分情况,如果同时考虑一个孩子左右两边孩子的评分情况,那么在更新糖果数的时候,就可能会产生错误,因为同时根据一个孩子的左右孩子的评分情况和糖果分配情况来更新当前孩子的糖果数的话,可能左孩子还是右孩子的糖果数还没更新,于是就产生了错误。
先按照最低要求给每个孩子分配一颗糖果,然后从左往右遍历每个孩子的评分,如果右边孩子比左边孩子评分高的话,就让右边孩子的糖果数比左边孩子的糖果数多一个(贪心:局部只要右边的孩子分比左边的孩子高的话,右边的孩子糖果数就比左边的孩子糖果数多;全局使得相邻的孩子中,评分高的右孩子比左孩子分配到的糖果多);然后从后往前遍历(这里一定要从后往前遍历,从前往后遍历的话,用来比较的右边孩子的糖果数可能后面还会被更新,所以可能会得到错误的结果)每个孩子的评分,如果左边孩子比右边孩子评分高的话,就让左边孩子取当前糖果分配数和右边孩子糖果分配数中的较大者(贪心),这样就能够达到全局最优:相邻的孩子中,评分高的孩子获得更多的糖果。
int candy(int* ratings, int ratingsSize){ int* candyArr = malloc(sizeof(int) * ratingsSize); for (int i = 0; i < ratingsSize; i++) { candyArr[i] = 1; } // 从前往后,考虑右边孩子比左边孩子高分的情况 for (int i = 1; i < ratingsSize; i++) { if (ratings[i] > ratings[i - 1]) { candyArr[i] = candyArr[i - 1] + 1; } } // 从后往前,考虑左边孩子比右边孩子高分的情况 for (int i = ratingsSize - 2; i >= 0; i--) { if (ratings[i] > ratings[i + 1]) { candyArr[i] = candyArr[i] > candyArr[i + 1] + 1 ? candyArr[i] : candyArr[i + 1] + 1 ; } } int sum = 0; for (int i = 0; i < ratingsSize; i++) { sum += candyArr[i]; } return sum; }