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.pswp.cn/web/92625.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/92625.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

配置timer控制 IO的输出(STC8)

使用STC8的Timer控制IO输出 STC8系列单片机具有多个定时器&#xff0c;可以用于精确控制IO口的输出状态。以下是使用Timer0和Timer1控制IO输出的方法。 初始化Timer0 配置Timer0为16位自动重装模式&#xff0c;用于周期性控制IO输出&#xff1a; /************************ 定时…

【Python练习】086. 编写一个函数,实现简单的DHCP服务器功能

086. 编写一个函数,实现简单的DHCP服务器功能 086. 编写一个函数,实现简单的DHCP服务器功能 安装依赖库 示例代码 代码说明 示例输出 注意事项 扩展功能 DHCP服务器功能实现方法 依赖库安装 基本功能实现 功能说明 运行方法 注意事项 扩展功能 086. 编写一个函数,实现简单的…

生产环境Tomcat运行一段时间后,如何测试其性能是否满足后续使用

要测试生产环境中已运行一段时间的Tomcat性能是否满足后续使用需求&#xff0c;需从基础监控、负载压力测试、配置合理性校验、稳定性验证等多维度入手&#xff0c;结合工具和实际业务场景定位瓶颈&#xff0c;确保其能应对未来可能的流量增长。以下是具体方法和步骤&#xff1…

Qt中的设计模式:经典的MVC,MVP和MVVM

Qt中的设计模式&#xff1a;经典的MVC&#xff0c;MVP和MVVM 前言 ​ 笔者这里最近正在研究经典的三大 Model/View 框架&#xff0c;不得不说&#xff0c;我先前的确写过Qt在这里的体现&#xff0c;但是&#xff0c;笔者认为之前的文章中&#xff0c;我只是机械的memcpy的Qt的…

Windows浮动ip怎么配置

Windows浮动IP怎么配置&#xff0c;达到IP漂移的效果&#xff0c;方法肯定是有的&#xff0c;这里我推荐一款好用的高可用Vip漂移软件PanguVip&#xff0c;我们先看下最终达到的效果图&#xff0c;如下所示PanguVip软件免费下载百度网盘为您提供文件的网络备份、同步和分享服务…

[langchain] Sync streaming vs Async Streaming

我不太清楚langchain中的sync stream 和 async steam有什么关系和区别sync stream from langchain.chat_models import init_chat_model from langchain_deepseek.chat_models import ChatDeepSeek import dotenv dotenv.load_dotenv()messages [ ("system", &quo…

nginx下lua的实现机制、Lua错误处理、面向对象

nginx下lua的实现机制 nginxlua概述 nginx&#xff1a;功能由模块提供。 http模块、events模块&#xff0c;mail模块。 处理http请求的时候&#xff0c;可以利用模块做一些功能&#xff1a;eg&#xff1a;登录校验&#xff0c;js合并&#xff0c;数据库访问&#xff0c;鉴权。 …

Axure基于中继器实现的组件库(导航菜单、动态表格)

摘要 本文将为您详细介绍基于 Axure 的中继器组件库中的 9 个独特组件&#xff0c;这些组件不仅能够极大地提升您的原型设计效率&#xff0c;还能为您的项目增添令人惊叹的交互效果和视觉呈现。 引言 在当今快速发展的数字产品设计领域&#xff0c;原型设计工具的革新不断推动着…

Kafka 生产者与消费者分区策略全解析:从原理到实践

一、生产者分区策略1.1 分区好处&#xff08;1&#xff09;便于合理使用存储资源&#xff0c;每个Partition在一个Broker上存储&#xff0c;可以把海量的数据按照分区切割成一块一块数据存储在多台Broker上。合理控制分区的任务&#xff0c;可以实现负载均衡的效果。&#xff0…

高频面试点:深入理解 TCP 三次握手与四次挥手

在网络通信的世界里,TCP(Transmission Control Protocol,传输控制协议)是确保数据可靠传输的基石。其中,三次握手建立连接、四次挥手断开连接的过程,更是 Java 秋招面试中的高频考点。今天,我们就深入剖析这两个关键过程,结合原理、代码示例与面试真题,帮你吃透知识点…

k8s-nfs实现创建sc的两种方式

法一&#xff1a;基于 官方 NFS CSI 插件 法二&#xff1a;基于 nfs-subdir-external-provisioner 法一 官方 NFS CSI 插件 大致步骤# 安装 NFS sudo apt update sudo apt install -y nfs-kernel-server # 创建共享目录 sudo mkdir -p /data/nfs sudo chmod 777 /data/nfs # 配…

n8n 入门指南:更适合跨境出海搞钱的AI智能体

如果你最近刷到 AI 圈的分享应该会发现——n8n 又火起来了。其实 n8n 早在 2020 年左右就被程序员玩过一波&#xff0c;当时很多人拿它做网站自动发邮件、消息转发之类的“流程自动化”。但那时候 AI 还没这么卷&#xff0c;大家也没觉得多有用。n8n为什么最近又翻红&#xff1…

【数据分享】各省农业土地流转率(2010-2023)

数据介绍土地流转是推动农业规模化、现代化发展的关键机制。为助力相关研究&#xff0c;现分享一份覆盖全国30个省级行政区、时间跨度为2010-2023年的农业土地流转率面板数据集。本数据直接提取自权威统计年报&#xff0c;具有较高的参考价值。一、数据概览覆盖范围&#xff1a…

音视频时间戳获取与同步原理详解

引言&#xff1a;为什么音视频同步如此重要&#xff1f; 在音视频技术领域&#xff0c;"同步"是决定用户体验的核心要素。想象一下观看电影时画面与声音错位0.5秒的场景&#xff1a;角色说话时嘴唇动作与声音不匹配&#xff0c;爆炸场景的视觉冲击先于音效到达——这…

Day38--动态规划--322. 零钱兑换,279. 完全平方数,139. 单词拆分,56. 携带矿石资源(卡码网),背包问题总结

Day38–动态规划–322. 零钱兑换&#xff0c;279. 完全平方数&#xff0c;139. 单词拆分&#xff0c;56. 携带矿石资源&#xff08;卡码网&#xff09;&#xff0c;背包问题总结 今天的是几道经典的“完全背包”题目。前两道题目&#xff0c;要区分求的是“价值”&#xff0c;还…

应用层Http协议(1)

应用层Http协议&#xff08;1&#xff09; 在互联网世界中&#xff0c;HTTP&#xff08;HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff09;是一个至关重要的协议。它定义了客户端&#xff08;如浏览器&#xff09;与服务器之间如何通信&#xff0c;以交换或传…

elementui input无法输入问题

背景。开发小程序。自定义表单在pc段设置好input输入框属性后。 在小程序端无法输入原因&#xff1a;长度受限制&#xff0c;导致input组件的maxlength属性认为长度是0导致无法输入任何值。看解释是应为遇到空字符串等情况会设置为0解决。因为未找到设置maxlength为0处&#xf…

算法_python_学习记录_02

算法学习和视频学习过程中&#xff0c;有许多前几天还不知道的知识点&#xff0c;现在一点一点归纳整理出来&#xff0c;稳步前进&#xff0c;前进~ 20_贪心算法系列题 00_参考文档 详解贪心算法&#xff08;Python实现贪心算法典型例题&#xff09;_顺序贪婪算法-CSDN博客P…

Meta AI水印计划的致命缺陷——IEEE Spectrum深度文献精读

一、原文信息 标题: Metas AI Watermarking Plan Is Flimsy, at Best 中文译名: Meta的AI水印计划脆弱不堪 作者: David Evan Harris(加州大学伯克利分校)、Lawrence Norden(纽约大学法学院) 发表日期: 2024年3月5日 发表期刊: IEEE Spectrum 二、原文全文翻译 Met…

gpt-oss 全量技术解读

一、概述 gpt-oss 是 OpenAI 发布的开放权重&#xff08;open-weight&#xff09;模型系列&#xff0c;面向强推理、Agent 能力与多样化应用场景。 提供两种规格&#xff1a; gpt-oss-120b&#xff1a;面向生产与高推理需求&#xff0c;单卡 80GB GPU&#xff08;如 NVIDIA …