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

分发糖果

文章目录

  • 分发糖果
    • 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_right

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_right

if 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 # 谷底设为1
    if b > 0: # 可以往左走
        left = b - 1
        while (left >= 0) and (left not in bottoms): # left not in bottoms 注意不要碰到波峰波谷结合体
            if left in tops: # 遇到波峰,先更新成最大值,再break
                res[left] = max(res[left + 1] + 1, res[left])
                break
            else:
                res[left] = res[left + 1] + 1 # 没有异常,直接+1
            left = left - 1

    if b < len(ratings) - 1:
        right = b + 1
        while (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_right

            if 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_right

            if is_top:
                tops.append(i)

        for b in bottoms:
            res[b] = 1
            if b > 0:
                left = b - 1
                while (left >= 0) and (left not in bottoms):
                    if left in tops:
                        res[left] = max(res[left + 1] + 1, res[left])
                        break
                    else:
                        res[left] = res[left + 1] + 1
                    left = left - 1

            if b < len(ratings) - 1:
                right = b + 1
                while (right < len(ratings)) and (right not in bottoms):
                    res[right] = res[right - 1] + 1
                    if right in tops:
                        break
                    right = right + 1
        candy = 0
        for c in res:
            candy = candy + c
        return 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_right

            if 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_right

            if is_top:
                tops.append(i)
        # 将bottoms变成set,方便查找
        bottoms_set = set(bottoms)


        for b in bottoms:
            res[b] = 1
            if b > 0:
                left = b - 1
                while (left >= 0) and (left not in bottoms_set):
                    if left in tops:
                        res[left] = max(res[left + 1] + 1, res[left])
                        break
                    else:
                        res[left] = res[left + 1] + 1
                    left = left - 1

            if b < len(ratings) - 1:
                right = b + 1
                while (right < len(ratings)) and (right not in bottoms_set):
                    res[right] = res[right - 1] + 1
                    if right in tops:
                        break
                    right = right + 1
        candy = 0
        for c in res:
            candy = candy + c
        return 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_right

        if 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_right

        if is_top:
            tops.append(i)
    draw_pic(ratings, bottoms, tops, res)


    for b in bottoms:
        res[b] = 1
        draw_pic(ratings, bottoms, tops, res)
        if b > 0:
            left = b - 1
            while (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)
                    break
                else:
                    res[left] = res[left + 1] + 1
                    draw_pic(ratings, bottoms, tops, res)
                left = left - 1

        if b < len(ratings) - 1:
            right = b + 1
            while (right < len(ratings)) and (right not in bots):
                res[right] = res[right - 1] + 1
                draw_pic(ratings, bottoms, tops, res)
                if right in tops:
                    break
                right = right + 1
    candy = 0
    for c in res:
        candy = candy + c
    draw_pic(ratings, bottoms, tops, res)
    return candy
def draw_pic(ratings, bottoms, tops, res):
    import matplotlib.pyplot as plt
    import 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)))
    # show
    plt.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)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

kafka的详细安装部署

简介&#xff1a; Kafka是一个分布式流处理平台&#xff0c;主要用于处理高吞吐量的实时数据流。Kafka最初由LinkedIn公司开发&#xff0c;现在由Apache Software Foundation维护和开发。 Kafka的核心是一个分布式发布-订阅消息系统&#xff0c;它可以处理大量的消息流&#…

开始使用Spring Boot Admin吧-使用Nacos注册SBA

什么是 Spring Boot Admin&#xff08;SBA&#xff09;? Spring Boot Admin 是 codecentric 公司开发的一款开源社区项目&#xff0c;目标是让用户更方便的管理以及监控 Spring Boot 应用。 应用可以通过我们的Spring Boot Admin客户端&#xff08;通过HTTP的方式&#xff0…

浙江启用无人机巡山护林模式,火灾扑救效率高

为了保护天然的森林资源&#xff0c;浙江当地林业部门引入了一种创新技术&#xff1a;林业无人机。这些天空中的守护者正在重新定义森林防火和护林工作的方式。 当下正值天气干燥的季节&#xff0c;这些无人机开始了它们的首次大规模任务。它们在指定的林区内自主巡逻&#xff…

C++二分查找或并集查找:交换得到字典序最小的数组

作者推荐 利用广度优先或模拟解决米诺骨牌 本文涉及的基础知识点 二分查找算法合集 题目 给你一个下标从 0 开始的 正整数 数组 nums 和一个 正整数 limit 。 在一次操作中&#xff0c;你可以选择任意两个下标 i 和 j&#xff0c;如果 满足 |nums[i] - nums[j]| < limi…

Ubuntu20.04部署TVM流程及编译优化模型示例

前言&#xff1a;记录自己安装TVM的流程&#xff0c;以及一个简单的利用TVM编译模型并执行的示例。 1&#xff0c;官网下载TVM源码 git clone --recursive https://github.com/apache/tvmgit submodule init git submodule update顺便完成准备工作&#xff0c;比如升级cmake版本…

Vue3中调用外部iframe链接方法

业务场景&#xff0c;点击某个按钮需要跳转到外部iframe的地址&#xff0c;但是需要在本项目内显示。以前项目中写过调用外部链接的功能&#xff0c;是有菜单的&#xff0c;但是这次是按钮&#xff0c;所以不能直接把地址配到菜单里。 实现方法&#xff1a;在本地路由文件里写个…

解决git与huggingface项目下载速度慢或者失败的问题

git clone 项目报错 比如使用git clone 下载项目&#xff1a; git clone https://github.com/ChuRuaNh0/FastSam_Awsome_TensorRT.git有时候会报以下错误&#xff1a; fatal: unable to access ‘https://github.com/xxx.git/’: Failed to connect to github.com port 443 …

Unity打出的安卓包切换后台再恢复前台,卡顿许久问题记录

连接AndroidStudio发现当切换后台时提示&#xff1a;D/Unity: Multi-casting "[IP] 192.168.31.231 [Port] 55000 [Flags] 19 [Guid] 1268732307 [EditorId] 264356214 [Version] 1048832 [Id] AndroidPlayer(11,Xiaomi_M2012K11AC192.168.31.231) [Debug] 0 [PackageName…

MATLAB实战 | 不同形式的三维曲面图

通常&#xff0c;MATLAB中绘制三维曲面图&#xff0c;先要生成网格数据&#xff0c;再调用mesh函数和surf函数绘制三维曲面。若曲面用含两个自变量的参数方程定义&#xff0c;则还可以调用fmesh函数和fsurf函数绘图。若曲面用隐函数定义&#xff0c;则可以调用fimplicit3函数绘…

医学影像PACS源码:PACS系统的基础知识(DICOM、HL7、SWF)

1、PACS PACS是Picture Archiving and Communication Systems首字母缩写&#xff0c;全称为影像储存和传输系统&#xff0c;涉及放射医学、计算机技术、通讯技术及数字图像技术等&#xff0c;是医院信息系统的重要组成部分&#xff0c;是将数字医疗设备(如X线、CT、MRI、超声、…

(C++)字符串相乘

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 题目链接如下&#xff1a; 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能&#xff0c;轻松拿下世界 IT 名…

C# WPF上位机开发(第一个应用)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 万事开头难&#xff0c;很多事情都是难在第一步。走出了这第一步&#xff0c;回过头看以前走的每一步&#xff0c;发现其实也不难。用c# wpf编写界…

nodejs+vue+mysql皮具行李箱包包网上商城购物网站

本系统可分为两个大的模块&#xff0c;即前台用户模块和后台管理员模块&#xff0c;前台用户模块用户可以进行浏览查询皮具的各种信息&#xff0c;添加购物车&#xff0c;下订单等各种操作。后台管理员模块管理员可以进行皮具的处理&#xff0c;还有处理订单&#xff0c;皮具分…

【C/PTA —— 12.指针1(课内实践)】

C/PTA —— 12.指针1&#xff08;课内实践&#xff09; 6-1 交换两个整数的值6-2 利用指针找最大值6-3 字符串的连接6-4 移动字母 6-1 交换两个整数的值 void fun(int* a, int* b) {int* tmp *a;*a *b;*b tmp; }6-2 利用指针找最大值 void findmax(int* px, int* py, int* p…

easyexcel指定sheet页动态给行列加背景色

easyexcel&#xff0c;有多个sheet页&#xff0c;某些sheet页的行、列动态需要加背景色 import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.Head; import com.alibaba.excel.write.handler.CellWriteHandler; import com.alibaba.excel.write.m…

任意多个磁盘时的kickstart配置方法

最近工作遇到一个需求&#xff1a;当机器中存在任意多个磁盘时&#xff0c;kickstart配置文件应该如何编写&#xff1f; 我查询了一些资料&#xff0c;得到的结果大多是针对特定数量的磁盘的配置&#xff08;比如&#xff0c;2个&#xff0c;3个&#xff09;。 那么假如因为某些…

opencv-医学图像预处理

医学图像预处理通常需要针对特定任务和数据集的特点进行定制。以下是一些常见的医学图像预处理步骤&#xff0c;可以使用OpenCV以及其他相关库来实现&#xff1a; 导入相关的库 import cv2 import matplotlib.pyplot as plt1. 读取图像 image cv2.imread(r"C:\Users\m…

[ CSS ] 内容超出容器后 以...省略

内容超出容器后 以…省略 当前效果 代码 <template><div class"box">有志者&#xff0c;事竟成&#xff0c;破釜沉舟&#xff0c;百二秦关终属楚; 有心人&#xff0c;天不负&#xff0c;卧薪尝胆&#xff0c;三千越甲可吞吴</div> </templa…

ESP32-Web-Server编程- JS 基础 4

ESP32-Web-Server编程- JS 基础 4 概述 HTML 内联事件处理器&#xff0c;你永远不应该使用 HTML 事件处理器属性——因为那些已经过时了&#xff0c;使用它们是不好的做法。 在前端编程中&#xff0c;除了将期望发生的事件写为 JS 文件外&#xff0c;还可以使用一些组件自带…