如何使用多种算法解决LeetCode第135题——分发糖果问题

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容,和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣!

期待与您一起探索技术、持续学习、一步步打怪升级 欢迎订阅本专栏❤️❤️

题目描述

老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。你需要按照以下要求,帮助老师给这些孩子分发糖果:

  1. 每个孩子至少分到一个糖果。
  2. 评分更高的孩子必须比他两侧的邻位孩子获得更多的糖果。

你需要最少准备多少糖果。

示例 1:

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

示例 2:

输入: [1,2,2]
输出: 4
解释: 你可以分别给这三个孩子分发 1、2、1 颗糖果。
     第三个孩子只得到 1 颗糖果,这满足题目要求。

方法一:两次遍历法

解题步骤

  1. 创建一个糖果数组,初始化每个孩子的糖果数为 1。
  2. 从左到右遍历,如果当前孩子的评分高于前一个孩子,则当前孩子的糖果数设置为前一个孩子的糖果数加一。
  3. 从右到左遍历,如果当前孩子的评分高于后一个孩子,并且当前孩子的糖果数不大于后一个孩子的糖果数,则当前孩子的糖果数设置为后一个孩子的糖果数加一。
  4. 返回糖果数组的总和。

Python 示例

def candy(ratings):
    n = len(ratings)
    candies = [1] * n

    # 从左到右遍历
    for i in range(1, n):
        if ratings[i] > ratings[i - 1]:
            candies[i] = candies[i - 1] + 1

    # 从右到左遍历
    for i in range(n - 2, -1, -1):
        if ratings[i] > ratings[i + 1] and candies[i] <= candies[i + 1]:
            candies[i] = candies[i + 1] + 1

    return sum(candies)

# Example usage
ratings = [1, 0, 2]
print(candy(ratings))  # Output: 5

ratings = [1, 2, 2]
print(candy(ratings))  # Output: 4

算法分析

  • 时间复杂度:O(N),其中 N 是孩子的数量。需要遍历两次数组。
  • 空间复杂度:O(N),用于存储糖果数量的数组。

算法图解与说明

考虑 ratings = [1, 0, 2]

初始化糖果数组:candies = [1, 1, 1]

左到右遍历:
索引1: 1 (评分 0) <= 0 (评分 1), 无变化
索引2: 2 (评分 2) > 0 (评分 0), 更新 candies[2] = candies[1] + 1 = 2
结果: candies = [1, 1, 2]

右到左遍历:
索引1: 0 (评分 1) > 0 (评分 1) 且 candies[1] <= candies[2], 无变化
索引0: 1 (评分 1) > 0 (评分 0), 更新 candies[0] = candies[1] + 1 = 2
结果: candies = [2, 1, 2]

总糖果数: 2 + 1 + 2 = 5

方法二:单次遍历法

解题步骤

  1. 创建一个糖果数组,初始化每个孩子的糖果数为 1。
  2. 使用一个标记数组来记录相邻孩子之间的关系(评分高的标记为 1,评分低的标记为 -1,相等标记为 0)。
  3. 单次遍历,根据标记调整糖果数,确保所有条件都满足。
  4. 返回糖果数组的总和。

Python 示例

def candy(ratings):
    n = len(ratings)
    if n == 0:
        return 0
    if n == 1:
        return 1

    candies = [1] * n

    for i in range(1, n):
        if ratings[i] > ratings[i - 1]:
            candies[i] = candies[i - 1] + 1

    for i in range(n - 2, -1, -1):
        if ratings[i] > ratings[i + 1]:
            candies[i] = max(candies[i], candies[i + 1] + 1)

    return sum(candies)

# Example usage
ratings = [1, 0, 2]
print(candy(ratings))  # Output: 5

ratings = [1, 2, 2]
print(candy(ratings))  # Output: 4

算法分析

  • 时间复杂度:O(N),其中 N 是孩子的数量。需要遍历两次数组。
  • 空间复杂度:O(1),只使用了常数级别的额外空间。

算法图解与说明

考虑 ratings = [1, 0, 2]

初始化糖果数组:candies = [1, 1, 1]

单次遍历:
从左到右遍历:
索引1: 1 (评分 0) <= 0 (评分 1), 无变化
索引2: 2 (评分 2) > 0 (评分 0), 更新 candies[2] = candies[1] + 1 = 2
结果: candies = [1, 1, 2]

从右到左遍历:
索引1: 0 (评分 1) > 0 (评分 1) 且 candies[1] <= candies[2], 无变化
索引0: 1 (评分 1) > 0 (评分 0), 更新 candies[0] = candies[1] + 1 = 2
结果: candies = [2, 1, 2]

总糖果数: 2 + 1 + 2 = 5

这两种方法都能有效地解决分发糖果的问题,确保每个孩子至少得到一颗糖果,并且评分更高的孩子比相邻孩子获得更多糖果。选择哪种方法可以根据具体场景和个人喜好而定。

🌹🌹如果觉得这篇文对你有帮助的话,记得一键三连关注、赞👍🏻、收藏是对作者最大的鼓励,非常感谢 ❥(^_-)

❤️❤️作者知识有限,如有错误,请各位大佬评论区批评指正,不胜感激❥(^_-)
在这里插入图片描述

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
KMP算法是一种字符串匹配算法,用于在一个文本串S内查找一个模式串P的出现位置。它的时间复杂度为O(n+m),其中n为文本串的长度,m为模式串的长度。 KMP算法的核心思想是利用已知信息来避免不必要的字符比较。具体来说,它维护一个next数组,其中next[i]表示当第i个字符匹配失败时,下一次匹配应该从模式串的第next[i]个字符开始。 我们可以通过一个简单的例子来理解KMP算法的思想。假设文本串为S="ababababca",模式串为P="abababca",我们想要在S中查找P的出现位置。 首先,我们可以将P的每个前缀和后缀进行比较,得到next数组: | i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | --- | - | - | - | - | - | - | - | - | | P | a | b | a | b | a | b | c | a | | next| 0 | 0 | 1 | 2 | 3 | 4 | 0 | 1 | 接下来,我们从S的第一个字符开始匹配P。当S的第七个字符和P的第七个字符匹配失败时,我们可以利用next[6]=4,将P向右移动4个字符,使得P的第五个字符与S的第七个字符对齐。此时,我们可以发现P的前五个字符和S的前五个字符已经匹配成功了。因此,我们可以继续从S的第六个字符开始匹配P。 当S的第十个字符和P的第八个字符匹配失败时,我们可以利用next[7]=1,将P向右移动一个字符,使得P的第一个字符和S的第十个字符对齐。此时,我们可以发现P的前一个字符和S的第十个字符已经匹配成功了。因此,我们可以继续从S的第十一个字符开始匹配P。 最终,我们可以发现P出现在S的第二个位置。 下面是KMP算法的C++代码实现:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数据分析螺丝钉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值