【刷题笔记】分糖果||数组||暴力通过||符合思维方式||多案例分析

分发糖果

文章目录

  • 分发糖果
    • 1 题目描述
    • 2 题目分析
      • 2.1 寻找波峰波谷
      • 2.2 从波底往波峰攀爬!
      • 2.2 计算糖果
    • 3 代码
    • 附录1

1 题目描述

https://leetcode.cn/problems/candy/

n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。

你需要按照以下要求,给这些孩子分发糖果:

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

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

示例 1:

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

示例 2:

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

2 题目分析

首先利用实例分析,我们假设所有小孩子的评分为[17, 18, 86, 49, 18, 42, 39, 72, 4, 98]

在这里插入图片描述

题目让我们返回需要准备的最少糖果,最直接的想法就是:找到所有的波底分数对应的小孩,设置其糖果为1,然后朝着两边的波峰,逐步+1。

我“寻找波峰波谷”、“分发糖果”这些步骤的绘制图像的代码放在了附录1中,你可以传入你自定义的评分或者随机生成的评分,绘制出每一步的状态,然后可以在UUTool这个网站上设置gif。

在这里插入图片描述

在这里插入图片描述

2.1 寻找波峰波谷

当然,如果图像都是像上面那种评分还好,我们还有一种特殊情况:如果出现连续的相等评分怎么办?
在这里插入图片描述

如上图,出现了连续3个87,我们看看“题目描述”中怎么应对这种情况?示例2中,面对这种情况,是直接将第二个得87分的孩子的糖果设为1(高分不完全,等于完全不高分,太残酷了/(ㄒoㄒ)/~~),那么从实际来看,对于第二个87分这种情况,我们视为波谷。

  • 如何判断波峰?假设当前索引为i
    • i==0,则不用判断i的左边,只考虑i的分数是否大于等于i+1的分数。
    • i==len(ratings)-1,则不用考虑i的右边,只考虑i的分数是否大于等于i-1的分数。

换句话说,我们对i是否为波峰的判断,分为ii-1的rating相比以及和i+1的rating相比。如果i==0,不考虑左边;如果i==len(ratings)-1,不考虑右边。

如何判断波谷,其实也是同样的方式。

is_t_left = (i == 0) or (ratings[i - 1] <= ratings[i])
is_t_right = (i == len(ratings) - 1) or (ratings[i] >= ratings[i + 1])
is_top = is_t_left and is_t_rightis_b_left = (i == 0) or (ratings[i - 1] >= ratings[i])
is_b_right = (i == len(ratings) - 1) or (ratings[i] <= ratings[i + 1])
is_bottom = is_b_left and is_b_rightif is_top:tops.append(i)
if is_bottom:bottoms.append(i)

这里有一个疑问,为什么是“大于等于”,而不是“大于”?

很简单,我们看第一个87,其和右边相等,但是还是满足是一个波峰。

在这里插入图片描述

但是这样的判断方式有一个问题,假设ratings[i]==ratings[i-1]==ratings[i+1]i既满足对于波峰的判断条件,也满足对于波谷的判断条件,也就是说,i这个点即是波峰也是波谷。

没事,只要我们能判断出来这个i是波谷就行,叠加一个波峰的标志对后面没有影响,看后续代码就行。

在这里插入图片描述

2.2 从波底往波峰攀爬!

已经到达谷底了,往哪走都是上升!!————不是鲁迅说的

在这里插入图片描述

接下来,我们对所有的bottom进行遍历,先将bottom位置设为1,然后往左往右分别+1。

这里需要注意了,有些点既是top也是bottom,假设我们从i开始向左向右,只要碰到bottom,不管是不是top,都要停下来。

然后,我们看上面那张图,从i=0向右到达2,从i==4向左到达2,到达top的时候都会对应一个值,这里恰好都是3,那么我再举一个例子:

在这里插入图片描述

这张图中,从不同的方向到达top,一个对应2,一个对应3,我们取最大值。这样就可以满足candy[2]>candy[1],也满足candy[2]>candy[3]

for b in bottoms:res[b] = 1 # 谷底设为1if b > 0: # 可以往左走left = b - 1while (left >= 0) and (left not in bottoms): # left not in bottoms 注意不要碰到波峰波谷结合体if left in tops: # 遇到波峰,先更新成最大值,再breakres[left] = max(res[left + 1] + 1, res[left])breakelse:res[left] = res[left + 1] + 1 # 没有异常,直接+1left = left - 1if b < len(ratings) - 1:right = b + 1while (right < len(ratings)) and (right not in bottoms):res[right] = res[right - 1] + 1 # 包括top也一起更新if right in tops:break # 这里为什么直接break呢,因为此时的top还没有被除了b小孩外的其他小孩到达过。right = right + 1

2.2 计算糖果

candy = 0
for c in res:candy = candy + c

3 代码

class Solution(object):def candy(self, ratings):""":type ratings: List[int]:rtype: int"""bottoms = []tops = []res = [0 for _ in range(len(ratings))]for i in range(len(ratings)):is_b_left = (i == 0) or (ratings[i - 1] >= ratings[i])is_b_right = (i == len(ratings) - 1) or (ratings[i] <= ratings[i + 1])is_bottom = is_b_left and is_b_rightif is_bottom:bottoms.append(i)is_t_left = (i == 0) or (ratings[i - 1] <= ratings[i])is_t_right = (i == len(ratings) - 1) or (ratings[i] >= ratings[i + 1])is_top = is_t_left and is_t_rightif is_top:tops.append(i)for b in bottoms:res[b] = 1if b > 0:left = b - 1while (left >= 0) and (left not in bottoms):if left in tops:res[left] = max(res[left + 1] + 1, res[left])breakelse:res[left] = res[left + 1] + 1left = left - 1if b < len(ratings) - 1:right = b + 1while (right < len(ratings)) and (right not in bottoms):res[right] = res[right - 1] + 1if right in tops:breakright = right + 1candy = 0for c in res:candy = candy + creturn candy

此时我们注意到,(left not in bottoms)(right not in bottoms)可能会增加耗时,那么我考虑可以增加一个set来代替遍历查询

# 将bottoms变成set,方便查找
bottoms_set = set(bottoms)
(left not in bottoms_set)
(right not in bottoms_set)

class Solution(object):def candy(self, ratings):""":type ratings: List[int]:rtype: int"""bottoms = []tops = []res = [0 for _ in range(len(ratings))]for i in range(len(ratings)):is_b_left = (i == 0) or (ratings[i - 1] >= ratings[i])is_b_right = (i == len(ratings) - 1) or (ratings[i] <= ratings[i + 1])is_bottom = is_b_left and is_b_rightif is_bottom:bottoms.append(i)is_t_left = (i == 0) or (ratings[i - 1] <= ratings[i])is_t_right = (i == len(ratings) - 1) or (ratings[i] >= ratings[i + 1])is_top = is_t_left and is_t_rightif is_top:tops.append(i)# 将bottoms变成set,方便查找bottoms_set = set(bottoms)for b in bottoms:res[b] = 1if b > 0:left = b - 1while (left >= 0) and (left not in bottoms_set):if left in tops:res[left] = max(res[left + 1] + 1, res[left])breakelse:res[left] = res[left + 1] + 1left = left - 1if b < len(ratings) - 1:right = b + 1while (right < len(ratings)) and (right not in bottoms_set):res[right] = res[right - 1] + 1if right in tops:breakright = right + 1candy = 0for c in res:candy = candy + creturn candy

但是好像并没有什么卵用,大家可以尽情优化。

附录1

def candy(ratings):""":type ratings: List[int]:rtype: int"""bottoms = []tops = []bots = []res = [0 for _ in range(len(ratings))]for i in range(len(ratings)):is_b_left = (i == 0) or (ratings[i - 1] >= ratings[i])is_b_right = (i == len(ratings) - 1) or (ratings[i] <= ratings[i + 1])is_bottom = is_b_left and is_b_rightif is_bottom:bottoms.append(i)bots.append(i)is_t_left = (i == 0) or (ratings[i - 1] <= ratings[i])is_t_right = (i == len(ratings) - 1) or (ratings[i] >= ratings[i + 1])is_top = is_t_left and is_t_rightif is_top:tops.append(i)draw_pic(ratings, bottoms, tops, res)for b in bottoms:res[b] = 1draw_pic(ratings, bottoms, tops, res)if b > 0:left = b - 1while (left >= 0) and (left not in bots):if left in tops:res[left] = max(res[left + 1] + 1, res[left])draw_pic(ratings, bottoms, tops, res)breakelse:res[left] = res[left + 1] + 1draw_pic(ratings, bottoms, tops, res)left = left - 1if b < len(ratings) - 1:right = b + 1while (right < len(ratings)) and (right not in bots):res[right] = res[right - 1] + 1draw_pic(ratings, bottoms, tops, res)if right in tops:breakright = right + 1candy = 0for c in res:candy = candy + cdraw_pic(ratings, bottoms, tops, res)return candy
def draw_pic(ratings, bottoms, tops, res):import matplotlib.pyplot as pltimport numpy as np# 绘制柱状图,ratings为红色,res为蓝色(透明度为0.5),绘制在同一个图中plt.plot(range(len(ratings)), ratings, color='r', zorder=1)plt.scatter(range(len(ratings)), ratings, color='r', zorder=100)# 将bottoms标记出来plt.scatter(bottoms, [ratings[i] for i in bottoms], color='g', zorder=100)# 将这些点添加文字`bottom`,并且放置在点的下方for i in bottoms:plt.text(i, ratings[i] - 0.5, 'bottom', ha='center', va='top', fontsize=10)# 将tops标记出来plt.scatter(tops, [ratings[i] for i in tops], color='y', zorder=100)# 将这些点添加文字`top`,并且放置在点的上方for i in tops:plt.text(i, ratings[i] + 0.5, 'top', ha='center', va='bottom', fontsize=10)plt.bar(range(len(ratings)), res, color='b', alpha=0.5)# 将数值绘制在柱状图上for x, y in enumerate(res):plt.text(x, y + 0.1, '%s' % y, ha='center', va='bottom')# 设置 x 轴刻度及标签plt.xticks(np.arange(len(ratings)), range(len(ratings)))# showplt.show()# 随机生成ratings
import random
ratings = [random.randint(0, 100) for _ in range(10)]
# 绘制折线图
import matplotlib.pyplot as plt
import numpy as np
plt.plot(range(len(ratings)), ratings)
plt.scatter(range(len(ratings)), ratings)
# 设置 x 轴刻度及标签
plt.xticks(np.arange(len(ratings)), range(len(ratings)))
# 绘制y值
for x, y in enumerate(ratings):plt.text(x, y + 1, '%s' % y, ha='center', va='bottom')
plt.show()candy(ratings)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/175029.shtml

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

相关文章

Unity性能优化技巧篇

资源导入优化 随着项目越来越大&#xff0c;资源越来越多&#xff0c;有一套资源导入自动化设置很有必要&#xff0c;它不但可以减少你的工作量&#xff0c;也能更好的统一管理资源&#xff0c;保证资源的导入设置最优&#xff0c;还不会出错。 AssetPostprocessor 在Unity中…

Mo0n(月亮) MCGS触摸屏在野0day利用,强制卡死锁屏

项目:https://github.com/MartinxMax/Mo0n 后面还会不会在,我可就不知道了奥…还不收藏点赞关注 扫描存在漏洞的设备 #python3 Mo0n.py -scan 192.168.0.0/24 入侵锁屏 #python3 Mo0n.py -rhost 192.168.0.102 -lock 解锁 #python3 Mo0n.py -rhost 192.168.0.102 -unlock …

【Spring Boot】Swagger的常用注解

在Swagger的开发过程中&#xff0c;我们需要在Controller代码等处添加相应的注解&#xff0c;以便可以提高生成的接口文档的可读性为了解决这些问题&#xff0c;Swagger提供了很多的注解&#xff0c;通过这些注解&#xff0c;我们可以更好更清晰的描述我们的接口&#xff0c;包…

相机内存卡照片删除怎么恢复?没有备份可这样操作

在使用相机时&#xff0c;不小心删除了重要的照片可能是每位摄影爱好者的噩梦。然而&#xff0c;通过一些恢复方法&#xff0c;我们有机会挽救被删除的照片。本文将详细介绍相机内存卡照片删除恢复的方法。 图片来源于网络&#xff0c;如有侵权请告知 如果您误删了相机内存卡中…

项目实战——苍穹外卖(DAY10)

如果之前有改过端口号造成WebSocket无法连接的&#xff0c;可以看本篇文章“来单提醒”前的内容进行解决。 课程内容 Spring Task 订单状态定时处理 WebSocket 来单提醒 客户催单 功能实现&#xff1a;订单状态定时处理、来单提醒和客户催单 订单状态定时处理&#xff1a…

242. 有效的字母异位词

这篇文章会收录到 :算法通关村第十二关-白银挑战字符串经典题目-CSDN博客 242. 有效的字母异位词 描述 : 给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的字母异位词。 注意&#xff1a;若 s 和 t 中每个字符出现的次数都相同&#xff0c;则称 s 和 t …

11【保姆级】-GO语言的struct

11【保姆级】-GO语言的struct 一、Go的面向对象1.1 说明 二、结构体2.1 结构体和结构体变量(实例)的区别和联系2.2 声明结构体 和 细节说明2.3 结构体在内存中的布局2.4 创建结构体和访问结构体的四种方式 在学习GO语言时&#xff1a; 先建立整体框架&#xff0c;然后再去抠细节…

C语言错误处理之sterror和perror函数以及断言处理方式

目录 前言 sterror函数 perror函数 断言处理方式 前言 在错误处理一中&#xff0c;我们解释了C语言三种处理方式中的错误号处理方式&#xff0c;这一篇我们在基于上一篇的基础上加入了sterror函数与perror函数&#xff0c;以及断言处理方式的内容...... sterror函数 包含…

fastsocket提升nginx CPS性能分析

fastsocket是针对单机网络性能优化&#xff0c;提升单机的cps。 提升现在单机7LB服务的性能&#xff0c;预计cps的性能提升一倍。 内核对nginx的性能瓶颈损耗主要在内核的三把锁。 1. accpet的全局队列的sk_lock锁 2. new_inode中的全局inode_lock锁 3. sock_alloc_file中的…

【每日一题】子数组的最小值之和

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;贡献法单调栈 写在最后 Tag 【贡献法】【单调栈】【数组】【2023-11-27】 题目来源 907. 子数组的最小值之和 题目解读 计算整数数组的连续子数组中最小值的和。 解题思路 本题朴素的解决思想是求出所有的连续子数组…

小航助学题库蓝桥杯题库stem选拔赛(21年1月)(含题库教师学生账号)

需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统&#xff08;含题库答题软件账号&#xff09;_程序猿下山的博客-CSDN博客 需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统&#xff08;含题库答题软件账号&#xff09;_程序猿下山的博客-CSD…

SQL Server:流程控制语言详解

文章目录 一、批处理、脚本和变量局部变量和全局变量1、局部变量2、全局变量 二、顺序、分支和循环结构语句1、程序注释语句2、BEGIN┅END语句块3、IF┅ELSE语句4、CASE语句5、WHILE语句6、BREAK和CONTINUE语句BREAK语句CONTINUE语句 三、程序返回、屏幕显示等语句1、RETURN语句…

Python continue的用法详解与转义字符及用法

Python continue的用法详解 continue 的功能和 break 有点类似&#xff0c;区别是 continue 只是忽略当次循环的剩下语句&#xff0c;接着开始下一次循环&#xff0c;并不会中止循环&#xff1b;而 break 则是完全中止循环本身。 如下程序示范了continue 的用法&#xff1a; # …

工程数学笔记 | 傅里叶级数/变换的本质理解

以下内容纯属个人学习记录&#xff0c;难免有误&#xff0c;欢迎指正~ 引子 虽已工作数宰&#xff0c;但当因为工作的需要再次碰到傅里叶级数/变换相关的知识时是还是难免汗流浃背&#xff0c;读书时的痛苦的回忆涌上心头&#xff0c;果然曾经欠下的总归是要偿还的&#xff0c…

Python基础语法之学习print()函数

Python基础语法之学习print函数 1、代码2、效果 1、代码 print("Hello World") print("Hello World1","Hello World2") print("Hello World1\n","Hello World2") print("Hello World",end" 默认结束符是行号…

传输层协议[精选]

网络: 跨主机通信. 互联网通信: 两点之间的通信路径有无数条. 集线器: 把一根网线差出来两根,但是同一时刻只能有一根线跑.交换机: 组建局域网.路由器: 本质就是将两个局域网连接起来 交换机和路由器之间的区别越来越模糊. 调制解调器: 使用电话线上网的时候,需要将电话线的模…

c++容器详解Vector、deque、list、set、multiset、map、multimap、queue、stcak、Array

容器 数据结构描述实现头文件向量(vector)连续存储的元素<vector>列表(list)由节点组成的双向链表,每个结点包含着一个元素<list>双向队列(deque)连续存储的指向不同元素的指针所组成的数组<deque>集合(set)由节点组成的红黑树,每个节点都包含着一个元素,…

C++:对象模型和this指针

对象模型&#xff1a; 成员变量和成员函数分开存储 在C中&#xff0c;类内的成员变量和成员函数分开存储 只有非静态成员变量才属于类的对象上 空对象占用空间&#xff1a; 1字节 C编译器会给每个空对象也分配一个字节空间&#xff0c;是为了区分空对象占内存的位置 每个…

根据密码构成规则检测密码字符串

从键盘输入密码字符串&#xff0c;程序根据给定密码构成规则检测并给出对应提示。 (笔记模板由python脚本于2023年11月27日 19:27:47创建&#xff0c;本篇笔记适合熟悉Python字符串str对象的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.…

Android12之logcat日志显示颜色和时间(一百六十七)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…