【LeetCode】135. Candy

一、问题描述

There are N children standing in a line. Each child is assigned a rating value.

You are giving candies to these children subjected to the following requirements:

  • Each child must have at least one candy.
  • Children with a higher rating get more candies than their neighbors.

What is the minimum candies you must give?

Example 1:

Input: [1,0,2]
Output: 5
Explanation: You can allocate to the first, second and third child with 2, 1, 2 candies respectively.

Example 2:

Input: [1,2,2]
Output: 4
Explanation: You can allocate to the first, second and third child with 1, 2, 1 candies respectively.
The third child gets 1 candy because it satisfies the above two conditions.

二、问题分析

本周选题是LeetCode上面一道难度为Hard的135题–Candy。这道题之所以是Hard难度,并不是因为代码量大或者实现困难,而是算法很精巧。由于我是按照Tag为Greedy去检索得到的题,因此自然而然我们应该考虑如何用贪心算法去实现。

题目要求每个等级高的孩子的糖数必须必他的邻居高,却没有规定如果两个等级相同邻居的糖数是怎样的。考虑初始化所有孩子一开始都只有一颗糖,如果他比他前面的孩子等级高,那么他的糖数就定为前一个孩子的糖数+1。这样从前到后扫描一次,我们即可得到每个等级更高的孩子都比他前面孩子的糖数多。

类似,再从后面向前扫描一遍,如果前面的孩子比他后面孩子等级高,并且他的糖数不多于后面的孩子,那么我们设置他的糖数为后面孩子的糖数+1。这样从后向前扫描一遍,每个等级更高的孩子都比他后面孩子的糖数多;于此同时,这样设置并不会破坏之前从前向后扫描的逻辑(每个等级更高的孩子都比他前面孩子的糖数多)。

这样经过两次扫描,每个等级高的孩子的糖数也就比他两个邻居的都高了。因此我们也就得到了最终结果。这样的算法复杂度为O(n)(两次遍历数组即可)。

三、问题求解

针对问题分析,以下是c++源代码。

class Solution {
public:
    int candy(vector<int>& ratings) {
        int size = ratings.size();
        int result[size];
        for (int i = 0; i < size; i++) {
        	result[i] = 1;
        }
        for (int i = 1; i < size; i++) {
        	if (ratings[i] > ratings[i - 1]) {
        		result[i] = result[i - 1] + 1;
        	}
        }
        for (int i = size - 2; i >= 0; i--) {
        	if (ratings[i] > ratings[i + 1] && result[i] <= result[i + 1]) {
        		result[i] = result[i + 1] + 1;
        	}
        }
        int total = 0;
        for (int i = 0; i < size; i++) {
        	total += result[i];
        }
        return total;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值