每日一算法题-分糖果

119 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第27天,点击查看活动详情

一、题目

描述:
一群孩子做游戏,现在请你根据游戏得分来发糖果,要求如下:
1.每个孩子不管得分多少,起码分到一个糖果。
2.任意两个相邻的孩子之间,得分较多的孩子必须拿多一些糖果。(若相同则无此限制)
给定一个数组 arrarr 代表得分数组,请返回最少需要多少糖果。

输入: [1, 4, 3, 2, 5]
输出: 9

#include <iostream>
#include <vector>
using namespace std;

int candy(vector<int>& array) {
}

int main(int, char*[])
{
    vector<int> array = {1, 4, 3, 2, 5};
    cout << "need candy:" << candy(array) << endl;
}

二、分析

由题意可知,分糖果问题看似简单,实则暗藏杀机。
无论方向是从前面还是后面,从第一个人开始,你就无法确定应该发多少,因为当左右没有确定时,当前也是不能确定的。
这个时候就要考虑到进行问题划分了,通过将一个大问题划分成多个可以确定的小问题,从而去推动大问题的解决。
从题目来看,得分高的孩子必须比得分低的孩子分的多,那这里存在的确定情况就只有一种,就是后面的人得分比前面的人得分高,这样前面的人就不会被后面的人所影响,那我们只需要将所有的升序序列划分出来。
小问题划分出来之后,就要考虑怎么将小问题汇总了,两个相邻的小问题如何结合呢,就按照规则来,前面的小问题中最后一个小朋友的得分和后面的小问题中的第一个小朋友的得分进行比较,如果得分高于并且糖果小于,那就将前面的糖果数等于后面的糖果数+1就好了。
问题解决了,现在考虑最优,每个人最少1个,那小问题中,第一个人就1个,随后依次增加一个就好了。

三、模拟

  1. 1 1

  2. 1,4 1,2

  3. 1,4 1,2

    3 1

  4. 1,4 1,2

    3 1

    2 1

  5. 1,4 1,2

    3 1

    2,5 1,2

  6. 1,4 1,2

    3 2

    2,5 1,2

  7. 1,4 1,3

    3 2

    2,5 1,2

四、实现

int candy(vector<int>& array) {
    vector<int> shadow(array.size(), 1);
    for(size_t i = 1; i < array.size(); ++i){
        if(array.at(i) > array.at(i - 1)){
            shadow.at(i) = shadow.at(i - 1) + 1;
        }
    }
    int result = shadow.back();
    for(size_t i = shadow.size() - 2; i < shadow.size(); --i){
        if(array.at(i) > array.at(i + 1) && shadow.at(i) <= shadow.at(i + 1)){
            shadow.at(i) = shadow.at(i + 1) + 1;
        }
        result += shadow.at(i);
    }
    return result;
}

五、结言

糖果分的好,小朋友更爱你。

创作不易,留个赞再走吧!如果对文章内容有任何指正,欢迎评论!