当前位置: 首页 > news >正文

LeetCode 面试经典 150_数组/字符串_分发糖果(15_135_C++_困难)(贪心算法)

LeetCode 面试经典 150_数组/字符串_分发糖果(15_135_C++_困难)

    • 题目描述:
    • 输入输出样例:
    • 题解:
      • 解题思路:
        • 思路一(贪心算法):
      • 代码实现
        • 代码实现(思路一(贪心算法)):
        • 代码实现(对思路一代码进行优化):
        • 以思路一为例进行调试

题目描述:

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

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

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

输入输出样例:

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

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

提示:
n == ratings.length
1 <= n <= 2 * 109
0 <= ratings[i] <= 2 * 109

题解:

解题思路:

思路一(贪心算法):

1、左右代表相邻的两个元素(只考虑两个相邻元素)
->->->->->->->
左 > 右 ;右=1
左 < 右 ;右=左+1
左 = 右 ;右=1
<-<-<-<-<-<-<-
左 > 右 ;左=右+1
左 < 右 ;左=1
左 = 右 ;左=1
① 从 左->右 扫描时,先将每个孩子的糖果置为 1,如果相邻元素中右侧的元素比左侧大,则右侧元素的糖果数等于左侧糖果数+1。
② 从 右->左 扫描时,先将每个孩子的糖果置为 1,如果相邻元素中左侧的元素比右侧大,则左侧元素的糖果数等于右侧糖果数+1。
③ 再挑选出 左->右 和 右->左中较大的元素。

:ratings = [1,0,2],left 代表从左到右,right 代表从右到左。
left = [1,1,2]
right= [2,1,1]
ans = 2+1+2=5

2、复杂度分析:
① 时间复杂度:O(n),n 代表数组的长度,遍历三遍数组。
② 空间复杂度:O(n),n 代表数组的长度,使用 left 存储从左向右的糖果,使用 right 存储从右向左的糖果。

代码实现

代码实现(思路一(贪心算法)):
class Solution1 {
public:// 主函数,返回给定评分数组所需的糖果总数int candy(vector<int>& ratings) {int count = ratings.size(); // 获取评分数组的长度vector<int> left(count, 1); // 初始化一个长度为count的数组left,表示每个孩子至少有1颗糖// 从左到右遍历评分数组,计算每个孩子的糖果数(如果比前一个孩子的评分高,糖果数加1)for (int i = 1; i < count; i++) {if (ratings[i] > ratings[i - 1]) { // 如果当前孩子的评分高于前一个孩子left[i] = left[i - 1] + 1; // 当前孩子的糖果数比前一个孩子多1}}vector<int> right(count, 1); // 初始化一个长度为count的数组right,表示每个孩子至少有1颗糖// 从右到左遍历评分数组,计算每个孩子的糖果数(如果比下一个孩子的评分高,糖果数加1)for (int i = count - 2; i >= 0; i--) {if (ratings[i] > ratings[i + 1]) { // 如果当前孩子的评分高于下一个孩子right[i] = right[i + 1] + 1; // 当前孩子的糖果数比下一个孩子多1}}int ans = 0; // 用于存储总糖果数// 遍历所有孩子,取每个孩子在left和right数组中的最大值(这保证了当前孩子能够得到最大可能的糖果数)for (int i = 0; i < count; i++) {ans += max(left[i], right[i]); // 取最大值,避免重复计算}return ans; // 返回总糖果数}
};
代码实现(对思路一代码进行优化):
/** 优化存储空间(只使用一个额外的数组)* 只使用一个额外的数组存储 左->右 扫描的结果* 从 右->左 扫描时,边计算 右->左 的糖果数量,边计算ans(总糖果数)* 时间复杂度:O(n),遍历了两遍数组。* 空间复杂度:O(n),使用了一个额外的数组空间。*/
class Solution2 {
public:// 主函数,返回给定评分数组所需的糖果总数int candy(vector<int>& ratings) {int count = ratings.size(); // 获取评分数组的长度vector<int> left(count, 1); // 初始化一个长度为count的数组left,表示每个孩子至少有1颗糖// 从左到右遍历评分数组,计算每个孩子的糖果数(如果比前一个孩子的评分高,糖果数加1)for (int i = 1; i < count; i++) {if (ratings[i] > ratings[i - 1]) { // 如果当前孩子的评分高于前一个孩子left[i] = left[i - 1] + 1; // 当前孩子的糖果数比前一个孩子多1}}// 初始化右边的糖果数,先假设最后一个孩子右边没有其他孩子int ans = left[count-1];  // 初始总糖果数为最后一个孩子的糖果数int right = 1;  // 右侧的临时糖果数,初始化为1,因为每个孩子至少有1颗糖// 从右到左遍历评分数组,计算每个孩子的糖果数(如果比下一个孩子的评分高,糖果数加1)for (int i = count - 2; i >= 0; i--) {if (ratings[i] > ratings[i + 1]) { // 如果当前孩子的评分高于下一个孩子right = right + 1; // 当前孩子的糖果数增加} else {right = 1; // 如果当前孩子的评分不高于下一个孩子,糖果数恢复为1}// 更新总糖果数:取左边和右边糖果数的最大值// left[i]是从左到右计算的糖果数,right是从右到左计算的糖果数ans += max(right, left[i]); // 累加当前孩子的最大糖果数}return ans; // 返回总糖果数}
};
以思路一为例进行调试
#include<iostream>
#include<vector>
using namespace std;class Solution1 {
public:// 主函数,返回给定评分数组所需的糖果总数int candy(vector<int>& ratings) {int count = ratings.size(); // 获取评分数组的长度vector<int> left(count, 1); // 初始化一个长度为count的数组left,表示每个孩子至少有1颗糖// 从左到右遍历评分数组,计算每个孩子的糖果数(如果比前一个孩子的评分高,糖果数加1)for (int i = 1; i < count; i++) {if (ratings[i] > ratings[i - 1]) { // 如果当前孩子的评分高于前一个孩子left[i] = left[i - 1] + 1; // 当前孩子的糖果数比前一个孩子多1}}// 初始化右边的糖果数,先假设最后一个孩子右边没有其他孩子int ans = left[count-1];  // 初始总糖果数为最后一个孩子的糖果数int right = 1;  // 右侧的临时糖果数,初始化为1,因为每个孩子至少有1颗糖// 从右到左遍历评分数组,计算每个孩子的糖果数(如果比下一个孩子的评分高,糖果数加1)for (int i = count - 2; i >= 0; i--) {if (ratings[i] > ratings[i + 1]) { // 如果当前孩子的评分高于下一个孩子right = right + 1; // 当前孩子的糖果数增加} else {right = 1; // 如果当前孩子的评分不高于下一个孩子,糖果数恢复为1}// 更新总糖果数:取左边和右边糖果数的最大值// left[i]是从左到右计算的糖果数,right是从右到左计算的糖果数ans += max(right, left[i]); // 累加当前孩子的最大糖果数}return ans; // 返回总糖果数}
};int main(int argc, char const *argv[])
{vector<int> ratings = {1,0,2};Solution1 s;cout<<s.candy(ratings);return 0;
}

LeetCode 面试经典 150_数组/字符串_分发糖果(15_135)原题链接
欢迎大家和我沟通交流(✿◠‿◠)

http://www.dtcms.com/a/322447.html

相关文章:

  • 关于开发语言的一些效率 从堆栈角度理解一部分c java go python
  • nginx的安装
  • QML 鼠标穿透
  • 目标检测数据集 - 人脸佩戴检测数据集下载「包含VOC、COCO、YOLO三种格式」
  • 105-基于Flask的珍爱网相亲数据可视化分析系统
  • 深度学习图像分类数据集—七种虾病虫害分类
  • 制作 VSCode 插件
  • 2025华数杯B题一等奖方案:网络切片无线资源管理全解析(附Python/MATLAB代码)
  • 「iOS」————分类与扩展
  • Baumer高防护相机如何通过YoloV8深度学习模型实现火星陨石坑的检测识别(C#代码UI界面版)
  • rem:CSS中的相对长度单位
  • 从灵感枯竭到批量产出:无忧秘书创作平台如何重构内容生产者的工作流程?全环节赋能分析
  • Java基础-TCP通信单服务器接受多客户端
  • Pytorch模型复现笔记-FPN特征金字塔讲解+架构搭建(可直接copy运行)+冒烟测试
  • 强光干扰下误报率↓82%!陌讯多模态算法在睡岗检测的落地优化
  • 力扣 hot100 Day70
  • Linux高级编程-文件操作
  • 人类语义认知统一模型:融合脑科学与AI的突破
  • 工业场景反光衣识别准确率↑32%:陌讯多模态融合算法实战解析
  • Leetcode——556. 下一个更大元素 III
  • 重读《人件》Peopleware -(23)Ⅲ 适当人选 Ⅵ 乐在其中(下)
  • QT第三讲- 机制、宏、类库模块
  • 从免费到盈利:Coze智能体1小时封装变现全流程指南——井云科技
  • Spring Boot 2 集成 Redis 集群详解
  • 全栈:JDBC驱动版本和SQLserver版本是否有关系?怎么选择JDBC的版本号?
  • Spring 的原理探究
  • Java 大视界 -- Java 大数据在智能医疗手术机器人操作数据记录与性能评估中的应用(390)
  • 【Bluedroid】A2DP Sink音频焦点管理机制解析(update_audio_focus_state)
  • 【RabbitMQ】高级特性—事务、消息分发详解
  • 【n8n】学习n8n【10】:Github的项目n8n-workflows:本地安装2,053 个 n8n 工作流程集合:随时看随时抄/学习~