最少分发糖果数

题意:N个孩子站成一排,每个孩子分配一个分值。给这些孩子派发糖果,满足如下要求:
 (1).每个孩子至少一个
 (2).分值更高的孩子比他的相邻位的孩子获得更多的糖果
求至少分发多少糖果?

解题:先从左往右扫描,保证一个方向上相邻孩子分数更大的糖果更多;再从右往左扫描,保证另一方向上相邻孩子分数更大的糖果数更多

     int candy(vector<int> &ratings) {
        if(ratings.empty())
            return 0;
        int n = ratings.size();
        vector<int> vec(n, 1);
        int min = 0;
        vec[0] = 1;
        for(int i = 1; i < n; i++){
            if(ratings[i]> ratings[i-1])
                vec[i] = vec[i-1]+1;
        }
        for(int i = n-2; i >= 0; i--){
            if(ratings[i]> ratings[i+1] && vec[i] < vec[i+1]+1)
                vec[i] = vec[i+1]+1;
        }
        for(int i = 0; i< n; i++){
            min += vec[i];
        }
        return min;
    }
<think>好的,我现在需要解决用户的问题,即介绍C++中的分发糖果问题。首先,我要理解这个问题的大致内容。分发糖果通常是指LeetCode上的一个题目,题目描述是孩子们排成一排,每个孩子有一个评分,要求按照一定规则分发糖果,使得每个孩子至少有一个糖果,且评分更高的孩子必须比相邻的孩子获得更多的糖果。最终要计算最少需要多少糖果。 接下来,我需要回忆这个题目的具体要求和解决方法。通常,这个问题可以通过两次遍历来解决:一次从左到右,确保右边评分更高的孩子比左边多;另一次从右到左,处理左边评分更高的孩子。然后将两次遍历的结果取最大值,总和即为最少糖果。 我需要用C++来实现这个算法,所以要考虑如何编写代码。首先,定义一个组来存储每个孩子的糖果,初始化为1。然后进行两次遍历:第一次从左到右,如果右边评分高,则右边孩子的糖果为左边加一;第二次从右到左,如果左边评分高,则左边孩子的糖果取当前值和右边加一的最大值。最后累加所有糖果。 在解释过程中,要确保符合用户给出的系统级指令,比如学表达式用$...$,独立公式用$$...$$,并且使用中文。需要注意代码部分是否需要用LaTeX排版,但可能直接使用代码块更合适,不过用户没有特别说明,可能需要询问,但根据问题描述,用户可能更希望看到代码示例。 现在需要检查是否有遗漏的情况,比如所有孩子评分相同的情况,或者评分递增或递减的情况。比如评分是[1,2,3],那么分发应该是1,2,3,总和6;如果评分是[3,2,1],则分发3,2,1,总和6。如果评分是[1,3,4,5,2],则需要正确处理好峰值的情况。 在编写代码时,要注意组的初始化,两次遍历的顺序,以及最后的累加。可能需要测试几个例子来验证代码的正确性。 现在组织回答的结构:先介绍问题,再分步骤解释解决方法,然后给出代码示例,最后分析时间复杂度和可能的优化点。确保结构清晰,步骤明确,符合用户的要求。 需要确认是否所有学表达式都正确使用了$符号,例如在说明条件时,比如右边的评分比左边高,即ratings[i] > ratings[i-1],可能需要写成$ratings[i] > ratings[i-1]$,但实际代码中可能不需要学表达式,所以可能不需要。但如果有提到变量,比如评分组,可以用$ratings$表示。 最后,确保回答使用中文,语法正确,LaTeX格式正确,并且独立公式单独成段。不过在这个问题中可能涉及的学公式较少,主要是算法步骤和代码,但如果有需要,比如计算糖果的公式,可以用独立公式。</think>### C++实现分发糖果问题解析 #### 问题描述 给定一个长度为$n$的整组$ratings$,表示$n$个孩子的评分。需按以下规则分发糖果: 1. 每个孩子至少1颗糖果 2. 评分更高的孩子必须比相邻孩子获得更多糖果最少需要多少糖果。 #### 解决思路 采用**两次贪心遍历**策略: 1. **从左向右遍历**:确保右边孩子比左边评分高时,糖果更多 2. **从右向左遍历**:确保左边孩子比右边评分高时,糖果更多 #### 算法步骤 1. 初始化组$candies$,每个元素为1 2. 左→右遍历:若$ratings[i] > ratings[i-1]$,则$candies[i] = candies[i-1] + 1$ 3. 右→左遍历:若$ratings[i] > ratings[i+1]$,则$candies[i] = \max(candies[i], candies[i+1] + 1)$ 4. 累加所有糖果 #### 时间复杂度 $$O(n)$$ 仅需两次线性遍历,时间复杂度为线性级别 --- ### C++代码实现 ```cpp #include <vector> #include <algorithm> using namespace std; int candy(vector<int>& ratings) { int n = ratings.size(); if(n == 0) return 0; vector<int> candies(n, 1); // 从左向右遍历 for(int i = 1; i < n; ++i) { if(ratings[i] > ratings[i-1]) { candies[i] = candies[i-1] + 1; } } // 从右向左遍历 for(int i = n-2; i >= 0; --i) { if(ratings[i] > ratings[i+1]) { candies[i] = max(candies[i], candies[i+1] + 1); } } // 累加结果 int total = 0; for(int num : candies) { total += num; } return total; } ``` --- ### 实例验证 例1:输入$ratings = [1,0,2]$ - 第一次遍历后:$[1,1,2]$ - 第二次遍历后:$[2,1,2]$ - 总:$2+1+2=5$ 例2:输入$ratings = [1,3,4,5,2]$ - 第一次遍历后:$[1,2,3,4,1]$ - 第二次遍历后:$[1,2,3,4,1]$(右遍历无变化) - 总:$1+2+3+4+1=11$ --- ### 关键点说明 1. **双向遍历必要性**:仅单方向遍历无法处理递减序列 2. **取最大值操作**:保证同时满足左右两边约束条件 3. **空间复杂度优化**:可将组改为单个变量,但会降低代码可读性 此解法严格满足题目要求,且是最优时间复杂度解决方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值