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

news2024/11/18 16:48:09

分发糖果

文章目录

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

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

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

相关文章

怎么判断香港服务器的性能好不好?

随着互联网的不断发展&#xff0c;越来越多的人开始使用香港服务器来搭建自己的网站或者应用。但是&#xff0c;对于初次使用香港服务器的用户来说&#xff0c;往往会遇到一个问题&#xff1a;怎么判断香港服务器的性能好不好? 首先我们需要了解香港服务器的性能主要取决于哪些…

智能优化算法应用:基于蝙蝠算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于蝙蝠算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于蝙蝠算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.蝙蝠算法4.实验参数设定5.算法结果6.参考文献7.MATLAB…

iconfont 使用彩色图标

1、下载iconfont到本地 2、全局安装 iconfont-tools npm install -g iconfont-tools 3、在iconfont解压目录下执行命令、一直回车 iconfont-tools 4、文件拷贝 执行完上述命令后会生成iconfont-weapp目录&#xff0c;将iconfont-weapp目录下的iconfont-weapp- icon.css文件…

二叉树之推排序(升序)

目录 1.思路1.1大堆的建立方法1.2排序的方法 2.代码实现以及测试代码 1.思路 如何将一个堆进行排序&#xff0c;并变成升序&#xff1f;首先&#xff0c;如果要完成升序&#xff0c;那我们可以建立一个大堆&#xff0c;因为大堆可以选出一个最大的值放在堆的最上面&#xff0c…

舞蹈店管理系统服务预约会员小程序效果如何

舞蹈的作用很广&#xff0c;也有大量求学者&#xff0c;每个城市也有大小各异的舞蹈品牌店&#xff0c;他们承接商演、也会教学员、宣传拓展生意等&#xff0c;因此近些年来&#xff0c;随着互联网深入及短视频&#xff0c;舞蹈业市场规模也在增加。 而在门店经营中&#xff0…

Go 编程语言详解:用途、特性、与 Python 和 C++ 的比较

什么是Go? Go是一个跨平台、开源的编程语言Go可用于创建高性能应用程序Go是一种快速、静态类型、编译型语言&#xff0c;感觉上像动态类型、解释型语言Go由Robert Griesemer、Rob Pike和Ken Thompson于2007年在Google开发Go的语法类似于C Go用于什么&#xff1f; Web开发&…

QT中的 容器(container)-大全

一、介绍 Qt库提供了一套通用的基于模板的容器类&#xff0c;可以用这些类存储指定类型的项。比如&#xff0c;你需要一个大小可变的QString的数组&#xff0c;则使用QVector<QString>。 这些容器类比STL&#xff08;C标准模板库&#xff09;容器设计得更轻量、更安全并…

快速了解Spring AOP的概念及使用

文章目录 1. AOP概念1.1 什么是AOP&#xff1f;1.2 什么是Spring AOP&#xff1f; 2. Spring AOP的使用2.1 引入Spring AOP依赖2.2 编写AOP程序 3. Spring AOP详解3.1 Spring AOP核心概念1. 切点&#xff08;Pointcut&#xff09;2. 连接点&#xff08;Join Point&#xff09;3…

Linux系统编程 day06 进程间通信

进程间通信 1. 进程间通信的概念2. 匿名管道pipe3. 命名管道FIFO4. 内存映射区 1. 进程间通信的概念 在Linux的环境下&#xff0c;进程地址空间是相互独立的&#xff0c;每个进程有着各自不同的用户地址空间。一个进程不能访问另一个进程中的内容&#xff0c;要进行数据交换必…

[MySQL--基础]函数、约束

hello! 这里是欧_aita的频道。 今日语录:不管你觉得自己能做什么&#xff0c;或者你觉得你不能做什么&#xff0c;你都是对的。 祝福语&#xff1a;愿你的程序像太阳一样明亮&#xff0c;给世界带来温暖和光明。 大家可以在评论区畅所欲言&#xff0c;可以指出我的错误&#xf…

雷达公式实现(matlab)

雷达公式实现 代码来源&#xff1a;《雷达系统分析与设计(MATLAB版)(第三版)》 function [snr] radar_eq(pt,freq,g,sigma,b,nf,loss,range) % This program implements Eq.(1.63) %% Inputs:% pt——峰值功率&#xff0c;W% freq——雷达中心频率&#xff0c;Hz% g——天线…

Javaweb之Vue组件库Element之Form表单的详细解析

4.3.4 Form表单 4.3.4.1 组件演示 Form 表单&#xff1a;由输入框、选择器、单选框、多选框等控件组成&#xff0c;用以收集、校验、提交数据。 表单在我们前端的开发中使用的还是比较多的&#xff0c;接下来我们学习这个组件&#xff0c;与之前的流程一样&#xff0c;我们首…

AI 重构工业制造的故事 我们从大模型开始讲起

在数字化浪潮的推动下&#xff0c;工业制造领域正经历着一场前所未有的变革。人工智能&#xff08;AI&#xff09;作为这场变革的关键推动者之一&#xff0c;正以惊人的速度颠覆传统制造业。而大模型作为AI时代最先进的科技工具之一&#xff0c;或将成为引领这场变革的利器&…

零基础学Python第三天||写一个简单的程序

通过对四则运算的学习&#xff0c;已经初步接触了Python中内容&#xff0c;如果看官是零基础的学习者&#xff0c;可能有点迷惑了。难道敲几个命令&#xff0c;然后看到结果&#xff0c;就算编程了&#xff1f;这也不是那些能够自动运行的程序呀&#xff1f; 的确。到目前为止…

C语言错误处理之“非局部跳转<setjmp.h>头文件”

目录 前言 setjmp宏 longjmp函数 使用方法&#xff1a; 实例&#xff1a;测试setjmp与longjmp的使用 前言 通常情况下&#xff0c;函数会返回到它被调用的位置&#xff0c;我们无法使用goto语句改变它的返回的方向&#xff0c;因为goto语句只能跳转到同一函数内的某个标号…

数字档案馆档案咨询工作内容有哪些

档案咨询通常是指关于如何管理、存储、保护档案资料的问题。随着电子档案的日渐兴起&#xff0c;数字档案馆室的建设也是如火如荼&#xff0c;随之数字档案馆档案咨询的工作也逐渐增多。以下就是专久智能关于数字档案馆档案咨询工作内容有哪些的简要介绍&#xff1a; 1. 提供档…

软著项目推荐 深度学习动物识别 - 卷积神经网络 机器视觉 图像识别

文章目录 0 前言1 背景2 算法原理2.1 动物识别方法概况2.2 常用的网络模型2.2.1 B-CNN2.2.2 SSD 3 SSD动物目标检测流程4 实现效果5 部分相关代码5.1 数据预处理5.2 构建卷积神经网络5.3 tensorflow计算图可视化5.4 网络模型训练5.5 对猫狗图像进行2分类 6 最后 0 前言 &#…

【3D程序软件】SideFX与上海道宁一直为设计师提供程序化 3D动画和视觉效果工具,旨在创造高质量的电影效果

Houdini是一个 从头开始构建的程序系统 使艺术家能够自由工作 创建多次迭代 并与同事快速共享工作流程 Houdini FX为 视觉特效艺术家创作故事片 广告或视频游戏 凭借其基于程序节点的工作流程 Houdini FX可让 您更快地创建更多内容 从而缩短时间并 在所有创意任务中…

微信可以添加多少好友?

不知道有没有小伙伴好奇&#xff0c;微信到底可以添加多少好友&#xff1f;正好这个话题也上热搜了&#xff0c;我们就来了解一下。 有网友表示&#xff0c;自己的微信好友数量有10004个&#xff0c;已经不能再添加新的微信好友了。 一个微信号&#xff0c;可以添加的好友上限…

数字阅读用户规模持续增长 5.3亿人享受数字化阅读便利

近日,鲁迅长孙周令飞在接受采访时表示,自己“现在90%的时间刷视频,10%的时间看书”,引发网友热议。不少网友表示,鲁迅的孙子都花90%的时间刷视频,难怪现在没人看书了,其实这并不奇怪,也并不表明没人看书,而是读屏与读书并重的时代,纸质阅读与数字阅读共同构成了日常的阅读模式。…