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

分发糖果

文章目录

  • 分发糖果
    • 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.hqwc.cn/news/225838.html

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

相关文章

数据导入与预处理-第7章-数据清理工具OpenRefine

文章目录 数据清理工具OpenRefineOpenRefine简介下载与安装配置创建项目操作列收起列移动列和重排列移除该列与移除列重新定义列标题撤销与重做导出数据 进阶操作数据排序数据归类重复检测数据填充文本过滤数据转换 总结 数据清理工具OpenRefine OpenRefine简介 OpenRefine是…

NX二次开发UF_MTX3_x_vec 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_MTX3_x_vec Defined in: uf_mtx.h void UF_MTX3_x_vec(const double mtx [ 9 ] , double x_vec [ 3 ] ) overview 概述 Returns the X-direction vector of a matrix. 返回矩阵…

图片照片编辑SDK解决方案

图像和照片已经成为我们日常生活中不可或缺的一部分&#xff0c;无论是个人还是企业&#xff0c;都希望通过高质量的图像和照片来提升品牌形象&#xff0c;吸引更多的用户和客户。然而&#xff0c;图像和照片的编辑并不是一件简单的事情&#xff0c;它需要专业的技术和工具。这…

如何使用ArcGIS实现生态廊道模拟

生态廊道是指一种连接不同生态系统的走廊或通道&#xff0c;其建立有助于解决人类活动对野生动植物栖息地破碎化和隔离化的问题&#xff0c;提高生物多样性&#xff0c;减轻生态系统的压力。在城市化和农业开发不断扩张的背景下&#xff0c;生态廊道对于野生动植物的生存和繁衍…

基于单片机环境监测温湿度PM2.5系统设计

**单片机设计介绍&#xff0c;基于单片机环境监测温湿度PM2.5系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 设计一个基于单片机环境监测温湿度PM2.5的系统是一个非常有意义的项目。以下是一个基本的介绍&#xff1a; …

【Unity细节】为什么加载精灵图集直接导致Unity引擎崩溃

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 秩沅 原创 &#x1f636;‍&#x1f32b;️收录于专栏&#xff1a;unity细节和bug &#x1f636;‍&#x1f32b;️优质专栏 ⭐【…

蓝桥杯刷题day01——字符串中的单词反转

题目描述 你在与一位习惯从右往左阅读的朋友发消息&#xff0c;他发出的文字顺序都与正常相反但单词内容正确&#xff0c;为了和他顺利交流你决定写一个转换程序&#xff0c;把他所发的消息 message 转换为正常语序。 注意&#xff1a;输入字符串 message 中可能会存在前导空…

013 C++ set与map的用法

前言 本文将会向你介绍set与map的主要用法 set详解 int main() {set<string> s;vector<string> v { "Fan1","Fan2", "Fan3", "Fan4" };for (auto e : v){s.insert(e);}string input;while (cin >> input){if (s.…

成绩排序(练习链表)

&#xff08;图片别看错了&#xff0c;右边的是输出样例&#xff09; 前几天学了学链表&#xff0c;也把一些ADT格式敲了敲&#xff0c;但是还是没有实际用过 然后就选了一道排序题&#xff0c;顺便试了试插入排序 以前只知道有插入排序这个东西&#xff0c;但是用数组实现的…

Leetcode—18.四数之和【中等】

2023每日刷题&#xff08;四十一&#xff09; Leetcode—18.四数之和 实现代码 class Solution { public:vector<vector<int>> fourSum(vector<int>& nums, int target) {vector<vector<int>> ans;sort(nums.begin(), nums.end());int n …

供应链攻击的类型和预防

供应链攻击是一种面向软件开发人员和供应商的新兴威胁&#xff0c;目标是通过感染合法应用分发恶意软件来访问源代码、构建过程或更新机制。 供应链攻击是威胁行为者通过利用软件供应链中的漏洞进入组织网络的一种网络攻击&#xff0c;供应链攻击的目标可以是软件开发过程中的…

11月28日星期二今日早报简报微语报早读

11月28日星期二&#xff0c;农历十月十六&#xff0c;早报微语早读。 1、广电总局&#xff1a;有线电视终端系统默认设置应为“开机进入全屏直播”&#xff1b; 2、我国下一代互联网技术专利申请量10年超170万件&#xff1b; 3、字节收缩旗下游戏业务&#xff1a;已上线的游…